mCRL2
Loading...
Searching...
No Matches
coroutine.h
Go to the documentation of this file.
1// Author(s): David N. Jansen, Radboud Universiteit, Nijmegen, The Netherlands
2//
3// Copyright: see the accompanying file COPYING or copy at
4// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
5//
6// Distributed under the Boost Software License, Version 1.0.
7// (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
94
95#ifndef _COROUTINE_H
96#define _COROUTINE_H
97
98#include <cstdlib> // for std::size_t
99#include <cassert>
100#include <boost/preprocessor.hpp>
101
102
103
104
105
106/* ************************************************************************* */
107/* */
108/* I N T E R N A L S */
109/* */
110/* ************************************************************************* */
111
112
113
114
115
118#define _coroutine_ENUMDEF(lblseq) \
119 BOOST_PP_SEQ_FOR_EACH(_coroutine_ENUMDEF_1, , lblseq)
120#define _coroutine_ENUMDEF_1(r,data,label) \
121 BOOST_PP_CAT(BOOST_PP_CAT(_coroutine_, label), _enum),
122
123
124
125
126
127/* ************************************************************************* */
128/* */
129/* E X T E R N A L I N T E R F A C E */
130/* */
131/* ************************************************************************* */
132
133
134
135
136
142#define COROUTINES_SECTION \
143 do {{ if (1) {{{ do {
144
161#define COROUTINE_LABELS(locations) \
162 enum class _coroutine_labels { \
163 _coroutine_1_BEGIN_enum_, \
164 _coroutine_ENUMDEF(locations) \
165 ONLY_IF_DEBUG( _coroutine_ILLEGAL_enum_, ) \
166 _coroutine_2_BEGIN_enum_ \
167 } _coroutine_location[2] = \
168 { _coroutine_labels::_coroutine_2_BEGIN_enum_, \
169 _coroutine_labels::_coroutine_1_BEGIN_enum_ };\
170 std::size_t _coroutine_allowance = 1; \
171 _coroutine_label_switch: \
172 _coroutine_labels _coroutine_temp_location=_coroutine_location[1];\
173 _coroutine_location[1] = _coroutine_location[0]; \
174 ONLY_IF_DEBUG( _coroutine_location[0] = \
175 _coroutine_labels::_coroutine_ILLEGAL_enum_; )\
176 switch (_coroutine_temp_location) \
177 { \
178 case _coroutine_labels::_coroutine_1_BEGIN_enum_: \
179 do { do { \
180 switch (_coroutine_labels::_coroutine_2_BEGIN_enum_) {
181 //< to neutralize the case label of the first coroutine
182
183
192#define COROUTINE \
193 case _coroutine_labels::_coroutine_2_BEGIN_enum_: ; \
194 }} while (0); } while (0); \
195 do { do {{ \
196 {{ if (1) {
197
198
200#define END_COROUTINE \
201 TERMINATE_COROUTINE_SUCCESSFULLY(); \
202 } else assert(0 && "mismatched END_COROUTINE"); }} \
203 }} while (0); } while (0); \
204 do { do {{
205
206
208#define END_COROUTINES_SECTION \
209 ONLY_IF_DEBUG( default: ; ) \
210 }} while (0); } while (0); \
211 } \
212 assert(0 && "corrupted coroutine state"); \
213 _coroutine_label_terminate: ; \
214 } while(0); }}} else assert(0 && "mismatched END_COROUTINES_SECTION");\
215 }} while (0);
216
217
224/* The pattern of nested do { } while loops and if ... else statements used in
225the macro implementation should generate error messages if there is an
226unmatched COROUTINE_WHILE or END_COROUTINE_WHILE. */
227#define COROUTINE_WHILE(location, condition) \
228 do \
229 { \
230 if (1) \
231 { \
232 if (1) \
233 { \
234 goto _coroutine_ ## location ## _label; \
235 for ( ;; ) \
236 { \
237 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_ == \
238 _coroutine_location[0]);\
239 if (0 == --_coroutine_allowance) \
240 { \
241 _coroutine_location[0] = _coroutine_labels:: \
242 _coroutine_ ## location ## _enum;\
243 _coroutine_allowance = 2; \
244 goto _coroutine_label_switch; \
245 case _coroutine_labels::_coroutine_ ## location ## _enum: ; \
246 } \
247 _coroutine_ ## location ## _label: \
248 if (!(condition)) break;
249
250
252#define END_COROUTINE_WHILE \
253 } \
254 } \
255 else assert(0 && "mismatched END_COROUTINE_WHILE"); \
256 } \
257 else assert(0 && "mismatched END_COROUTINE_WHILE"); \
258 } \
259 while (0)
260
261
271#define COROUTINE_FOR(location, init, condition, update) \
272 do \
273 { \
274 (init); \
275 if (1) \
276 do \
277 {{ \
278 goto _coroutine_ ## location ## _label; \
279 for( ;; ) \
280 { \
281 (update); \
282 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_ == \
283 _coroutine_location[0]);\
284 if (0 == --_coroutine_allowance) \
285 { \
286 _coroutine_location[0] = _coroutine_labels:: \
287 _coroutine_ ## location ## _enum;\
288 _coroutine_allowance = 2; \
289 goto _coroutine_label_switch; \
290 case _coroutine_labels::_coroutine_ ## location ## _enum: ; \
291 } \
292 _coroutine_ ## location ## _label: \
293 if (!(condition)) break;
294
295
297#define END_COROUTINE_FOR \
298 } \
299 }} \
300 while (0); \
301 else assert(0 && "mismatched END_COROUTINE_FOR"); \
302 } \
303 while (0)
304
305
314#define COROUTINE_DO_WHILE(location,condition) \
315 do \
316 if (1) \
317 {{ \
318 goto _coroutine_ ## location ## _do_while_begin; \
319 do \
320 { \
321 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_ == \
322 _coroutine_location[0]);\
323 if (0 == --_coroutine_allowance) \
324 { \
325 _coroutine_location[0] = _coroutine_labels:: \
326 _coroutine_ ## location ## _enum;\
327 _coroutine_allowance = 2; \
328 goto _coroutine_label_switch; \
329 case _coroutine_labels::_coroutine_ ## location ## _enum: ; \
330 } \
331 if (!(condition)) break; \
332 _coroutine_ ## location ## _do_while_begin:
333
334
336#define END_COROUTINE_DO_WHILE \
337 } \
338 while (1); \
339 }} \
340 else assert(0 && "mismatched END_COROUTINE_DO_WHILE"); \
341 while (0)
342
343
348#define TERMINATE_COROUTINE_SUCCESSFULLY() \
349 do \
350 { \
351 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_\
352 == _coroutine_location[0]);\
353 goto _coroutine_label_terminate; \
354 (void) _coroutine_allowance; \
355 (void) _coroutine_location[1]; \
356 } \
357 while (0)
358
359
363#define ABORT_THIS_COROUTINE() \
364 do \
365 { \
366 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_\
367 == _coroutine_location[0]);\
368 _coroutine_allowance = 0; \
369 goto _coroutine_label_switch; \
370 (void) _coroutine_location[1]; \
371 } \
372 while (0)
373
374
378#define ABORT_OTHER_COROUTINE() \
379 do \
380 { \
381 assert(_coroutine_labels::_coroutine_ILLEGAL_enum_\
382 == _coroutine_location[0]);\
383 ONLY_IF_DEBUG( _coroutine_location[1] = \
384 _coroutine_labels::_coroutine_ILLEGAL_enum_; )\
385 _coroutine_allowance = 0; \
386 } \
387 while (0)
388
389#endif // ifndef _COROUTINE_H