reactor-c 1.0
C Runtime for Lingua Franca
Loading...
Searching...
No Matches
reaction_macros.h
Go to the documentation of this file.
1
25
26// Prevent inclusion twice in a row without an intervening inclusion of reaction_macros_undef.h.
27#ifndef REACTION_MACROS_H
28#define REACTION_MACROS_H
29
30// NOTE: According to the "Swallowing the Semicolon" section on this page:
31// https://gcc.gnu.org/onlinedocs/gcc-3.0.1/cpp_3.html
32// some of the following macros should use an odd do-while construct to avoid
33// problems with if ... else statements that do not use braces around the
34// two branches. Specifically, if the macro expands to more than one statement,
35// then the odd construct is needed.
36
48#define lf_set_present(out) lf_set_present((lf_port_base_t*)out)
49
73#define lf_set(out, val) \
74 do { \
75 out->value = val; \
76 lf_set_present(out); \
77 if (((token_template_t*)out)->token != NULL) { \
78 /* The cast "*((void**) &out->value)" is a hack to make the code */ \
79 /* compile with non-token types where value is not a pointer. */ \
80 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, *((void**)&out->value), 1); \
81 out->token = token; \
82 } \
83 } while (0)
84
98#ifndef __cplusplus
99#define lf_set_array(out, val, len) \
100 do { \
101 lf_set_present(out); \
102 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
103 out->token = token; \
104 out->value = token->value; \
105 out->length = len; \
106 } while (0)
107#else
108#define lf_set_array(out, val, len) \
109 do { \
110 lf_set_present(out); \
111 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
112 out->token = token; \
113 out->value = static_cast<decltype(out->value)>(token->value); \
114 out->length = len; \
115 } while (0)
116#endif
117
129#ifndef __cplusplus
130#define lf_set_token(out, newtoken) \
131 do { \
132 lf_set_present(out); \
133 _lf_replace_template_token((token_template_t*)out, newtoken); \
134 out->value = newtoken->value; \
135 out->length = newtoken->length; \
136 } while (0)
137#else
138#define lf_set_token(out, newtoken) \
139 do { \
140 lf_set_present(out); \
141 _lf_replace_template_token((token_template_t*)out, newtoken); \
142 out->value = static_cast<decltype(out->value)>(newtoken->value); \
143 out->length = newtoken->length; \
144 } while (0)
145#endif
146
158#define lf_set_destructor(out, dtor) ((token_type_t*)out)->destructor = dtor
159
171#define lf_set_copy_constructor(out, cpy_ctor) ((token_type_t*)out)->copy_constructor = cpy_ctor
172
173#ifdef MODAL_REACTORS
174
185#define lf_set_mode(mode) _LF_SET_MODE_WITH_TYPE(mode, _lf_##mode##_change_type)
186
187#endif // MODAL_REACTORS
188
190// For simplicity and backward compatability, don't require the environment-pointer when calling the timing API.
191// As long as this is done from the context of a reaction, `self` is in scope and is a pointer to the self-struct
192// of the current reactor.
193
198#define lf_tag() lf_tag(self->base.environment)
199
204#define lf_time_logical() lf_time_logical(self->base.environment)
205
211#define lf_time_logical_elapsed() lf_time_logical_elapsed(self->base.environment)
212
220#define lf_add_worker_thread() lf_add_worker_thread(self->base.environment)
221
228#define lf_added_worker_thread_count() lf_added_worker_thread_count(self->base.environment)
229
302#define lf_async(action, func, ...) \
303 ({ \
304 lf_async_state_t _lf_async_state; \
305 _lf_async_begin(&_lf_async_state, self, (action), NULL); \
306 __typeof__(func(__VA_ARGS__)) _lf_async_result = func(__VA_ARGS__); \
307 _lf_async_end(&_lf_async_state); \
308 _lf_async_result; \
309 })
310
337#define lf_await(port) _lf_await(self, (port))
338
347#define lf_await_resume(port) _lf_await_resume(self, (port))
348
358#define lf_reactor_name(reactor) lf_reactor_name(&reactor->base)
359
370#define lf_reactor_full_name(reactor) lf_reactor_full_name(&reactor->base)
371
372#endif // REACTION_MACROS_H