AceRoutine
1.4.2
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 "ClockInterface.h"
32 class AceRoutineTest_statusStrings;
33 class SuspendTest_suspendAndResume;
55 #if defined(__GNUC__) || defined(__clang__)
56 #define ACE_ROUTINE_DEPRECATED __attribute__((deprecated))
57 #elif defined(_MSC_VER)
58 #define ACE_ROUTINE_DEPRECATED __declspec(deprecated)
60 #pragma message("WARNING: Implement ACE_ROUTINE_DEPRECATED for this compiler")
61 #define ACE_ROUTINE_DEPRECATED
77 #define COROUTINE(...) \
78 GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__)
81 #define GET_COROUTINE(_1, _2, NAME, ...) NAME
84 #define COROUTINE1(name) \
85 struct Coroutine_##name : ace_routine::Coroutine { \
87 int runCoroutine() override; \
89 Coroutine_##name :: Coroutine_##name() { \
91 int Coroutine_##name :: runCoroutine()
94 #define COROUTINE2(className, name) \
95 struct className##_##name : className { \
96 className##_##name(); \
97 int runCoroutine() override; \
99 className##_##name :: className##_##name() { \
101 int className##_##name :: runCoroutine()
111 #define EXTERN_COROUTINE(...) \
112 GET_EXTERN_COROUTINE(\
113 __VA_ARGS__, EXTERN_COROUTINE2, EXTERN_COROUTINE1)(__VA_ARGS__)
118 #define GET_EXTERN_COROUTINE(_1, _2, NAME, ...) NAME
121 #define EXTERN_COROUTINE1(name) \
122 struct Coroutine_##name : ace_routine::Coroutine { \
123 Coroutine_##name(); \
124 int runCoroutine() override; \
126 extern Coroutine_##name name
129 #define EXTERN_COROUTINE2(className, name) \
130 struct className##_##name : className { \
131 className##_##name(); \
132 int runCoroutine() override; \
134 extern className##_##name name
137 #define COROUTINE_BEGIN() \
138 void* p = this->getJump(); \
139 if (p != nullptr) { \
147 #define COROUTINE_LOOP() \
155 #define COROUTINE_YIELD_INTERNAL() \
157 __label__ jumpLabel; \
158 this->setJump(&& jumpLabel); \
164 #define COROUTINE_YIELD() \
166 this->setYielding(); \
167 COROUTINE_YIELD_INTERNAL(); \
168 this->setRunning(); \
181 #define COROUTINE_AWAIT(condition) \
183 this->setYielding(); \
185 COROUTINE_YIELD_INTERNAL(); \
186 } while (!(condition)); \
187 this->setRunning(); \
205 #define COROUTINE_DELAY(delayMillis) \
207 this->setDelayMillis(delayMillis); \
208 this->setDelaying(); \
210 COROUTINE_YIELD_INTERNAL(); \
211 } while (!this->isDelayExpired()); \
212 this->setRunning(); \
216 #define COROUTINE_DELAY_MICROS(delayMicros) \
218 this->setDelayMicros(delayMicros); \
219 this->setDelaying(); \
221 COROUTINE_YIELD_INTERNAL(); \
222 } while (!this->isDelayMicrosExpired()); \
223 this->setRunning(); \
241 #define COROUTINE_DELAY_SECONDS(delaySeconds) \
243 this->setDelaySeconds(delaySeconds); \
244 this->setDelaying(); \
246 COROUTINE_YIELD_INTERNAL(); \
247 } while (!this->isDelaySecondsExpired()); \
248 this->setRunning(); \
255 #define COROUTINE_END() \
257 __label__ jumpLabel; \
259 this->setJump(&& jumpLabel); \
264 namespace ace_routine {
267 extern const __FlashStringHelper*
const sStatusStrings[];
276 template <
typename T_CLOCK>
279 friend class ::AceRoutineTest_statusStrings;
280 friend class ::SuspendTest_suspendAndResume;
515 printer.print(sStatusStrings[
mStatus]);
605 return T_CLOCK::millis();
614 return T_CLOCK::micros();
624 return T_CLOCK::seconds();
658 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.