AceRoutine
1.4.1
A low-memory, fast-switching, cooperative multitasking library using stackless coroutines on Arduino platforms.
|
Go to the documentation of this file.
25 #ifndef ACE_ROUTINE_COROUTINE_H
26 #define ACE_ROUTINE_COROUTINE_H
30 #include <AceCommon.h>
31 #include "ClockInterface.h"
33 class AceRoutineTest_statusStrings;
34 class SuspendTest_suspendAndResume;
56 #if defined(__GNUC__) || defined(__clang__)
57 #define ACE_ROUTINE_DEPRECATED __attribute__((deprecated))
58 #elif defined(_MSC_VER)
59 #define ACE_ROUTINE_DEPRECATED __declspec(deprecated)
61 #pragma message("WARNING: Implement ACE_ROUTINE_DEPRECATED for this compiler")
62 #define ACE_ROUTINE_DEPRECATED
78 #define COROUTINE(...) \
79 GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__)
82 #define GET_COROUTINE(_1, _2, NAME, ...) NAME
85 #define COROUTINE1(name) \
86 struct Coroutine_##name : ace_routine::Coroutine { \
88 int runCoroutine() override; \
90 Coroutine_##name :: Coroutine_##name() { \
92 int Coroutine_##name :: runCoroutine()
95 #define COROUTINE2(className, name) \
96 struct className##_##name : className { \
97 className##_##name(); \
98 int runCoroutine() override; \
100 className##_##name :: className##_##name() { \
102 int className##_##name :: runCoroutine()
112 #define EXTERN_COROUTINE(...) \
113 GET_EXTERN_COROUTINE(\
114 __VA_ARGS__, EXTERN_COROUTINE2, EXTERN_COROUTINE1)(__VA_ARGS__)
119 #define GET_EXTERN_COROUTINE(_1, _2, NAME, ...) NAME
122 #define EXTERN_COROUTINE1(name) \
123 struct Coroutine_##name : ace_routine::Coroutine { \
124 Coroutine_##name(); \
125 int runCoroutine() override; \
127 extern Coroutine_##name name
130 #define EXTERN_COROUTINE2(className, name) \
131 struct className##_##name : className { \
132 className##_##name(); \
133 int runCoroutine() override; \
135 extern className##_##name name
138 #define COROUTINE_BEGIN() \
139 void* p = this->getJump(); \
140 if (p != nullptr) { \
148 #define COROUTINE_LOOP() \
156 #define COROUTINE_YIELD_INTERNAL() \
158 __label__ jumpLabel; \
159 this->setJump(&& jumpLabel); \
165 #define COROUTINE_YIELD() \
167 this->setYielding(); \
168 COROUTINE_YIELD_INTERNAL(); \
169 this->setRunning(); \
182 #define COROUTINE_AWAIT(condition) \
184 this->setYielding(); \
186 COROUTINE_YIELD_INTERNAL(); \
187 } while (!(condition)); \
188 this->setRunning(); \
206 #define COROUTINE_DELAY(delayMillis) \
208 this->setDelayMillis(delayMillis); \
209 this->setDelaying(); \
211 COROUTINE_YIELD_INTERNAL(); \
212 } while (!this->isDelayExpired()); \
213 this->setRunning(); \
217 #define COROUTINE_DELAY_MICROS(delayMicros) \
219 this->setDelayMicros(delayMicros); \
220 this->setDelaying(); \
222 COROUTINE_YIELD_INTERNAL(); \
223 } while (!this->isDelayMicrosExpired()); \
224 this->setRunning(); \
242 #define COROUTINE_DELAY_SECONDS(delaySeconds) \
244 this->setDelaySeconds(delaySeconds); \
245 this->setDelaying(); \
247 COROUTINE_YIELD_INTERNAL(); \
248 } while (!this->isDelaySecondsExpired()); \
249 this->setRunning(); \
256 #define COROUTINE_END() \
258 __label__ jumpLabel; \
260 this->setJump(&& jumpLabel); \
265 namespace ace_routine {
268 extern const __FlashStringHelper*
const sStatusStrings[];
277 template <
typename T_CLOCK>
280 friend class ::AceRoutineTest_statusStrings;
281 friend class ::SuspendTest_suspendAndResume;
516 printer.print(sStatusStrings[
mStatus]);
606 return T_CLOCK::millis();
615 return T_CLOCK::micros();
625 return T_CLOCK::seconds();
659 void insertAtRoot() {
bool isYielding() const
The coroutine returned using COROUTINE_YIELD().
static unsigned long coroutineMillis()
Returns the current millisecond clock.
static const Status kStatusYielding
Coroutine returned using the COROUTINE_YIELD() statement.
static const Status kStatusEnding
Coroutine executed the COROUTINE_END() statement.
uint16_t mDelayStart
Start time provided by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS(), or COROUTINE_DELAY_SECONDS().
CoroutineTemplate * mNext
Pointer to the next coroutine in a singly-linked list.
uint8_t Status
The execution status of the coroutine, corresponding to the COROUTINE_YIELD(), COROUTINE_DELAY(),...
CoroutineTemplate()
Constructor.
void setupCoroutine(const __FlashStringHelper *) ACE_ROUTINE_DEPRECATED
Deprecated method that does nothing.
bool isTerminated() const
The coroutine was terminated by the scheduler with a call to setTerminated().
void suspend()
Suspend the coroutine at the next scheduler iteration.
void setYielding()
Set the kStatusDelaying state.
void setDelaySeconds(uint16_t delaySeconds)
Configure the delay timer for delaySeconds.
~CoroutineTemplate()=default
Destructor.
static unsigned long coroutineMicros()
Returns the current microseconds clock.
static const Status kStatusSuspended
Coroutine has been suspended using suspend() and the scheduler should remove it from the queue upon t...
void reset()
Reset the coroutine to its initial state.
void resume()
Add a Suspended coroutine into the head of the scheduler linked list, and change the state to Yieldin...
void setJump(void *jumpPoint)
Pointer to label where execute will start on the next call to runCoroutine().
void setDelayMillis(uint16_t delayMillis)
Configure the delay timer for delayMillis.
static const Status kStatusRunning
Coroutine is currenly running.
Base class of all coroutines.
bool isRunning() const
The coroutine is currently running.
static const Status kStatusDelaying
Coroutine returned using the COROUTINE_DELAY() statement.
void setTerminated()
Set status to indicate that the Coroutine has been removed from the Scheduler queue.
Status getStatus() const
Return the status of the coroutine.
virtual int runCoroutine()=0
The body of the coroutine.
void setRunning()
Set the kStatusRunning state.
static const Status kStatusTerminated
Coroutine has ended and no longer in the scheduler queue.
bool isSuspended() const
The coroutine was suspended with a call to suspend().
bool isDelaySecondsExpired() const
Check if delay seconds time is over.
void setDelaying()
Set the kStatusDelaying state.
Class that manages instances of the Coroutine class, and executes them in a round-robin fashion.
bool isDone() const
The coroutine is either Ending or Terminated.
Status mStatus
Run-state of the coroutine.
uint16_t mDelayDuration
Delay time specified by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS() or, COROUTINE_DELAY_SECONDS().
void setupCoroutine(const char *) ACE_ROUTINE_DEPRECATED
Deprecated method that does nothing.
bool isDelayExpired() const
Check if delay millis time is over.
void * mJumpPoint
Address of the label used by the computed-goto.
bool isDelayMicrosExpired() const
Check if delay micros time is over.
bool isDelaying() const
The coroutine returned using COROUTINE_DELAY().
bool isEnding() const
The coroutine returned using COROUTINE_END().
static unsigned long coroutineSeconds()
Returns the current clock in unit of seconds, truncated to the lower 16-bits.
void * getJump() const
Pointer to label where execute will start on the next call to runCoroutine().
void setEnding()
Set the kStatusEnding state.
void statusPrintTo(Print &printer)
Print the human-readable string of the Status.
#define ACE_ROUTINE_DEPRECATED
Macro that indicates a deprecation.
virtual void setupCoroutine()
Perform coroutine initialization.
void setDelayMicros(uint16_t delayMicros)
Configure the delay timer for delayMicros.