OS  v1.8.0
Documentation
Loading...
Searching...
No Matches
coroutine.hpp
1#ifndef QOS_CPP_CO
2#define QOS_CPP_CO
3
4#include "include/types.hpp"
5#include "include/timer.hpp"
6#include "include/macro_overload.hpp"
7
8namespace qOS {
9
13 namespace co {
14
19
21 using state = base_t;
23
24 /*cstat -MISRAC++2008-0-1-4_b*/
25 const state UNDEFINED = -2;
26 const state SUSPENDED = -1;
27 const state BEGINNING = 0;
28 /*cstat +MISRAC++2008-0-1-4_b*/
29
30 class coContext;
31
32 enum class coAction {
33 CO_TIMEOUT_DISARM,
34 };
36
38 class position final {
39 state pos{ BEGINNING };
41 public:
42 state operator()(void) const
43 {
44 return pos;
45 }
46 position& operator=( co::state l )
47 {
48 pos = l;
49 return *this;
50 }
52 };
53
55 class handle final {
56 private:
57 co::state prev = { co::UNDEFINED };
58 coContext *ctx{ nullptr };
59 handle( handle const& ) = delete;
60 void operator=( handle const& ) = delete;
61 public:
62 handle() = default;
66 void try_restart( void ) noexcept;
70 void try_suspend( void ) noexcept;
75 void try_resume( void ) noexcept;
79 void try_set( co::state p ) noexcept;
84 explicit operator bool() const noexcept {
85 return ( nullptr != ctx );
86 }
87 friend class co::coContext;
88 };
89
91 class semaphore final {
92 private:
93 size_t count{ 1U };
94 void signal( void ) noexcept;
95 bool tryLock( void ) noexcept;
96 semaphore( semaphore const& ) = delete;
97 void operator=( semaphore const& ) = delete;
98 public:
107 explicit semaphore( size_t init ) : count( init ) {}
116 void set( size_t val ) noexcept;
117 friend class co::coContext;
118 };
119
121 /*cstat -MISRAC++2008-7-1-2*/
122 class coContext final {
123 private:
124 coContext( coContext const& ) = delete;
125 void operator=( coContext const& ) = delete;
126 co::state label{ co::BEGINNING };
127 qOS::timer tm;
128 public:
129 /*cstat -CERT-MSC40-C_a*/
130 coContext() = default;
131 inline void saveHandle( co::handle& h ) noexcept
132 {
133 h.ctx = this;
134 }
135 /*cstat +CERT-MSC40-C_a*/
136 inline static void saveHandle( void ) noexcept {}
137 inline static void semSignal( semaphore& s ) noexcept
138 {
139 s.signal();
140 }
141 inline static bool semTrylock( semaphore& s ) noexcept
142 {
143 return s.tryLock();
144 }
145 /*cstat -COP-member-uninit*/
146 inline coContext& operator=( co::state l )
147 {
148 label = l;
149 return *this;
150 }
151 /*cstat +COP-member-uninit*/
152 inline operator co::state() const
153 {
154 return label;
155 }
156 inline void operator()( qOS::duration_t t )
157 {
158 (void)tm.set( t );
159 }
160 inline void operator()( coAction action )
161 {
162 if ( coAction::CO_TIMEOUT_DISARM == action ) {
163 tm.disarm();
164 }
165 }
166 inline bool operator==( const co::state l ) const
167 {
168 return l == label;
169 }
170 inline bool operator!=( const co::state l ) const
171 {
172 return l != label;
173 }
174 inline bool timeout( void ) const
175 {
176 return tm.expired();
177 }
178 friend class handle;
179 };
180 /*cstat -MISRAC++2008-0-1-11*/
181
182 inline void crNOP( void ) noexcept {}
184
198 inline void reenter( void ) noexcept {}
199
215 inline void reenter( qOS::co::handle h ) noexcept { Q_UNUSED(h); }
216
224 inline void yield( void ) noexcept {}
225
230 inline void delay( qOS::duration_t t ) noexcept { Q_UNUSED(t); }
231
244 inline void waitUntil( bool condition ) noexcept { Q_UNUSED(condition); }
245
260 inline void waitUntil( bool condition, qOS::duration_t timeout ) noexcept { Q_UNUSED(condition); Q_UNUSED(timeout); }
261
275 inline bool timeoutExpired( void ) noexcept
276 {
277 return false;
278 }
279
285 inline void restart( void ) noexcept {}
286
294 inline void semWait( co::semaphore& sem ) noexcept { Q_UNUSED(sem); }
295
303 inline void semSignal( co::semaphore& sem ) noexcept { Q_UNUSED(sem); }
304
312 inline void getPosition( co::position &var ) noexcept { Q_UNUSED(var); }
313
320 inline void setPosition( co::position &var ) noexcept { Q_UNUSED(var); }
321
336 inline void perform( void ) noexcept { }
337
353 inline void perform( qOS::duration_t t ) noexcept { Q_UNUSED(t); }
354
370 inline void until( bool condition ) noexcept { Q_UNUSED(condition); }
371
372
373
374 inline void until( bool condition, qOS::duration_t timeout ) noexcept { Q_UNUSED(condition); Q_UNUSED(timeout); }
375 /*cstat +MISRAC++2008-0-1-11 +MISRAC++2008-7-1-2*/
376
378 }
379}
380/*============================================================================*/
382#define q_co_label ( __LINE__ )
383
384/*============================================================================*/
385#define reenter_0() q_co_reenter( Q_NONE )
386#define reenter_1(h) q_co_reenter( h )
387#define reenter(...) MACRO_OVERLOAD( reenter_ , __VA_ARGS__ )
388
389/*============================================================================*/
390// clang-format off
391#define q_co_reenter( h ) \
392reenter(); \
393static qOS::co::coContext co_ctx; \
394co_ctx.saveHandle( h ); \
395for ( ; co_ctx != qOS::co::SUSPENDED ; co_ctx = qOS::co::SUSPENDED ) \
396 if ( false ) { \
397 goto q_co_continue; \
398 q_co_continue: \
399 continue; \
400 } \
401 else if ( false ) { \
402 goto q_co_break; \
403 q_co_break: \
404 break; \
405 } \
406 else \
407 switch ( co_ctx ) \
408 case 0 : \
409
410/*============================================================================*/
411#define q_co_SaveRestore( label, init_action, pos_label_action ) \
412init_action; \
413for ( co_ctx = (label) ;; ) \
414 if ( false ) { \
415 case ( label ) : { \
416 pos_label_action \
417 break; \
418 } \
419 } \
420 else goto q_co_break \
421// clang-format on
422
423/*============================================================================*/
424#define q_co_cond( c ) \
425if ( !(c) ) { \
426 goto q_co_break; \
427} \
428
429/*============================================================================*/
430#define q_co_t_cond( c ) \
431if ( !( (c) || co_ctx.timeout() ) ) { \
432 goto q_co_break; \
433}
434/*============================================================================*/
435#define yield() q_co_yield( q_co_label )
436#define q_co_yield(label) \
437yield(); \
438q_co_SaveRestore( label, qOS::co::crNOP(), Q_NONE ) \
439
440/*============================================================================*/
441#define delay( t ) q_co_delay( q_co_label , t)
442#define q_co_delay( label, t ) \
443delay( t ); \
444q_co_SaveRestore( label, co_ctx(t) , q_co_t_cond(false) ) \
445
446/*============================================================================*/
447#define q_co_wu_1( c ) q_co_waitUntil( q_co_label , c )
448#define q_co_waitUntil( label, c ) \
449waitUntil( c ); \
450q_co_SaveRestore( label, qOS::co::crNOP(), q_co_cond(c) ) \
451
452#define q_co_wu_2( c, t ) q_co_timedWaitUntil( q_co_label , c, t )
453#define q_co_timedWaitUntil( label, c, t ) \
454waitUntil( c, t ); \
455q_co_SaveRestore( label, qOS::co::crNOP(), q_co_t_cond(c) ) \
456
457#define waitUntil(...) MACRO_OVERLOAD( q_co_wu_ , __VA_ARGS__ )
458/*============================================================================*/
459#define timeoutExpired() timeoutExpired() || co_ctx.timeout()
460
461/*============================================================================*/
462#define restart() q_co_restart
463#define q_co_restart \
464restart(); \
465co_ctx = qOS::co::BEGINNING; \
466goto q_co_break \
467
468/*============================================================================*/
469#define semWait( sem ) \
470semWait( sem ); \
471q_co_SaveRestore( q_co_label, qOS::co::crNOP(), q_co_cond( co_ctx.semTrylock( sem )) ) \
472
473/*============================================================================*/
474#define semSignal( sem ) \
475semSignal( sem ); \
476co_ctx.semSignal( sem ) \
477
478/*============================================================================*/
479#define getPosition( var ) q_co_get_pos( var, q_co_label )
480#define q_co_get_pos( var, label ) \
481getPosition( var ); \
482var = label; \
483case ( label ) : qOS::co::crNOP() \
484
485/*============================================================================*/
486#define setPosition( var ) co_res_pos( var, q_co_label )
487#define co_res_pos( var, label ) \
488setPosition( var ); \
489co_ctx = var(); \
490goto q_co_break \
491
492/*============================================================================*/
493#define perform_0() q_co_perform( co::coAction::CO_TIMEOUT_DISARM )
494#define perform_1( t ) q_co_perform( t )
495#define perform(...) MACRO_OVERLOAD( perform_ , __VA_ARGS__ )
496
497#define q_co_perform( t ) \
498perform(); \
499q_co_SaveRestore( q_co_label, co_ctx(t), Q_NONE ); \
500
501/*============================================================================*/
502#define until( c ) \
503until( c ); \
504q_co_cond( ( c ) || co_ctx.timeout() ) \
505/*============================================================================*/
506
507
509
510#endif /*QOS_CPP_CO*/
A Co-Routine handle.
Definition coroutine.hpp:55
handle()=default
void try_restart(void) noexcept
Try to execute the co::restart() statement externally.
void try_resume(void) noexcept
Try to resume the coroutine execution externally after a suspend operation.
void try_suspend(void) noexcept
Try to suspend the coroutine execution externally.
friend class co::coContext
Definition coroutine.hpp:87
void try_set(co::state p) noexcept
Try to execute co::setPosition() statement externally.
A placeholder for the Co-Routine current position or progress.
Definition coroutine.hpp:38
A Co-Routine Semaphore.
Definition coroutine.hpp:91
semaphore(size_t init)
Initializes a coroutine semaphore with a value for the counter. Internally, the semaphores use an siz...
Definition coroutine.hpp:107
void set(size_t val) noexcept
Set the coroutine semaphore with a value for the counter. Internally, the semaphores use an size_t to...
A non-blocking Timer object.
Definition timer.hpp:26
bool set(const qOS::duration_t tTime) noexcept
Set the expiration time for a timer. On success, the timer gets armed immediately.
bool expired(void) const noexcept
Non-Blocking timer check.
void disarm(void) noexcept
Disarms the timer object.
timeCount_t duration_t
The typedef that specified an time quantity, usually expressed in milliseconds.
Definition clock.hpp:18
bool timeoutExpired(void) noexcept
Check if the internal Co-routine timeout expires.
Definition coroutine.hpp:275
void restart(void) noexcept
This statement cause the running Coroutine to restart its execution at the place of the co::reenter()...
Definition coroutine.hpp:285
void delay(qOS::duration_t t) noexcept
Delay a coroutine for a given number of time.
Definition coroutine.hpp:230
base_t state
The intrinsic type of co::position to hold a coroutine progress.
Definition coroutine.hpp:21
void perform(void) noexcept
This statement start a blocking Job segment.
Definition coroutine.hpp:336
void semWait(co::semaphore &sem) noexcept
Carries out the "wait" operation on the semaphore. The wait operation causes the Co-routine to block ...
Definition coroutine.hpp:294
void until(bool condition) noexcept
This statement ends a blocking Job segment starting with the co::perform() statement.
Definition coroutine.hpp:370
void yield(void) noexcept
This statement is only allowed inside a Coroutine segment. co::yield return the CPU control back to t...
Definition coroutine.hpp:224
void reenter(void) noexcept
Defines a Coroutine segment. The co::reenter() statement is used to declare the starting point of a C...
Definition coroutine.hpp:198
void getPosition(co::position &var) noexcept
Labels the current position and saves it to var so it can be later restored by co::setPosition()
Definition coroutine.hpp:312
void setPosition(co::position &var) noexcept
Restores the Co-Routine position saved in var.
Definition coroutine.hpp:320
void waitUntil(bool condition) noexcept
Yields until the logical condition is met.
Definition coroutine.hpp:244
void semSignal(co::semaphore &sem) noexcept
Carries out the "signal" operation on the semaphore. The signal operation increments the counter insi...
Definition coroutine.hpp:303
@ SUSPENDED
Definition task.hpp:90
@ UNDEFINED
Definition task.hpp:87
int base_t
A type to instantiate a integer-base variable. This size of this type is implementation-defined.
Definition types.hpp:62
CoRoutines interfaces.
Definition coroutine.hpp:13
OS/Kernel interfaces.
Definition bytebuffer.hpp:7