AceRoutine
1.2.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>
32 class AceRoutineTest_statusStrings;
33 class SuspendTest_suspendAndResume;
66 #define COROUTINE(...) \
67 GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__)
70 #define GET_COROUTINE(_1, _2, NAME, ...) NAME
73 #define COROUTINE1(name) \
74 struct Coroutine_##name : ace_routine::Coroutine { \
76 int runCoroutine() override; \
78 Coroutine_##name :: Coroutine_##name() { \
79 setupCoroutine(F(#name)); \
81 int Coroutine_##name :: runCoroutine()
84 #define COROUTINE2(className, name) \
85 struct className##_##name : className { \
86 className##_##name(); \
87 int runCoroutine() override; \
89 className##_##name :: className##_##name() { \
90 setupCoroutine(F(#name)); \
92 int className##_##name :: runCoroutine()
102 #define EXTERN_COROUTINE(...) \
103 GET_EXTERN_COROUTINE(\
104 __VA_ARGS__, EXTERN_COROUTINE2, EXTERN_COROUTINE1)(__VA_ARGS__)
109 #define GET_EXTERN_COROUTINE(_1, _2, NAME, ...) NAME
112 #define EXTERN_COROUTINE1(name) \
113 struct Coroutine_##name : ace_routine::Coroutine { \
114 Coroutine_##name(); \
115 int runCoroutine() override; \
117 extern Coroutine_##name name
120 #define EXTERN_COROUTINE2(className, name) \
121 struct className##_##name : className { \
122 className##_##name(); \
123 int runCoroutine() override; \
125 extern className##_##name name
128 #define COROUTINE_BEGIN() \
129 void* p = getJump(); \
130 if (p != nullptr) { \
138 #define COROUTINE_LOOP() \
146 #define COROUTINE_YIELD_INTERNAL() \
148 __label__ jumpLabel; \
149 setJump(&& jumpLabel); \
155 #define COROUTINE_YIELD() \
158 COROUTINE_YIELD_INTERNAL(); \
172 #define COROUTINE_AWAIT(condition) \
176 COROUTINE_YIELD_INTERNAL(); \
177 } while (!(condition)); \
197 #define COROUTINE_DELAY(delayMillis) \
199 setDelayMillis(delayMillis); \
202 COROUTINE_YIELD_INTERNAL(); \
203 } while (!isDelayExpired()); \
208 #define COROUTINE_DELAY_MICROS(delayMicros) \
210 setDelayMicros(delayMicros); \
213 COROUTINE_YIELD_INTERNAL(); \
214 } while (!isDelayExpired()); \
236 #define COROUTINE_DELAY_SECONDS(delaySeconds) \
238 setDelaySeconds(delaySeconds); \
241 COROUTINE_YIELD_INTERNAL(); \
242 } while (!isDelayExpired()); \
250 #define COROUTINE_END() \
252 __label__ jumpLabel; \
254 setJump(&& jumpLabel); \
259 namespace ace_routine {
267 friend class ::AceRoutineTest_statusStrings;
268 friend class ::SuspendTest_suspendAndResume;
272 const ace_common::FCString&
getName()
const {
return mName; }
344 mJumpPoint =
nullptr;
525 printer.print(sStatusStrings[mStatus]);
532 void setJump(
void* jumpPoint) { mJumpPoint = jumpPoint; }
574 mDelayDuration = (delayMillis >= UINT16_MAX / 2)
586 mDelayDuration = (delayMicros >= UINT16_MAX / 2)
598 mDelayDuration = (delaySeconds >= UINT16_MAX / 2)
609 static const __FlashStringHelper*
const sStatusStrings[];
648 ace_common::FCString mName;
650 void* mJumpPoint =
nullptr;
653 uint16_t mDelayStart;
654 uint16_t mDelayDuration;
void setDelayMillis(uint16_t delayMillis)
Configure the delay timer for delayMillis.
Status getStatus() const
Return the status of the coroutine.
void reset()
Reset the coroutine to its initial state.
void suspend()
Suspend the coroutine at the next scheduler iteration.
void setRunning()
Set the kStatusRunning state.
void setEnding()
Set the kStatusEnding state.
static const uint8_t kDelayTypeSeconds
Delay using units of seconds.
void resume()
Add a Suspended coroutine into the head of the scheduler linked list, and change the state to Yieldin...
static const uint8_t kDelayTypeMillis
Delay using units of millis.
void * getJump() const
Pointer to label where execute will start on the next call to runCoroutine().
Class that manages instances of the Coroutine class, and executes them in a round-robin fashion.
void setDelayMicros(uint16_t delayMicros)
Configure the delay timer for delayMicros.
void setTerminated()
Set status to indicate that the Coroutine has been removed from the Scheduler queue.
static const Status kStatusRunning
Coroutine is currenly running.
virtual unsigned long coroutineMicros() const
Returns the current millisecond clock.
static const Status kStatusSuspended
Coroutine has been suspended using suspend() and the scheduler should remove it from the queue upon t...
bool isEnding() const
The coroutine returned using COROUTINE_END().
void setDelaying()
Set the kStatusDelaying state.
virtual unsigned long coroutineSeconds() const
Returns the current clock in unit of seconds, truncated to the lower 16-bits.
bool isRunning() const
The coroutine is currently running.
static const Status kStatusTerminated
Coroutine has ended and no longer in the scheduler queue.
uint8_t Status
The execution status of the coroutine, corresponding to the COROUTINE_YIELD(), COROUTINE_DELAY(),...
void setJump(void *jumpPoint)
Pointer to label where execute will start on the next call to runCoroutine().
static const Status kStatusEnding
Coroutine executed the COROUTINE_END() statement.
const ace_common::FCString & getName() const
Human-readable name of the coroutine.
void setDelaySeconds(uint16_t delaySeconds)
Configure the delay timer for delaySeconds.
bool isDone() const
The coroutine is either Ending or Terminated.
static const Status kStatusDelaying
Coroutine returned using the COROUTINE_DELAY() statement.
static const uint8_t kDelayTypeMicros
Delay using units of micros.
bool isDelayExpired() const
Check if delay time is over.
void setYielding()
Set the kStatusDelaying state.
void setupCoroutineOrderedByName(const char *name)
A version of setupCoroutine(const char*) where the ordering of the coroutines executed by CoroutineSc...
Base class of all coroutines.
virtual ~Coroutine()
Destructor.
bool isYielding() const
The coroutine returned using COROUTINE_YIELD().
virtual int runCoroutine()=0
The body of the coroutine.
void statusPrintTo(Print &printer)
Print the human-readable string of the Status.
bool isDelaying() const
The coroutine returned using COROUTINE_DELAY().
bool isSuspended() const
The coroutine was suspended with a call to suspend().
static const Status kStatusYielding
Coroutine returned using the COROUTINE_YIELD() statement.
bool isTerminated() const
The coroutine was terminated by the scheduler with a call to setTerminated().
virtual unsigned long coroutineMillis() const
Returns the current millisecond clock.
void setupCoroutine(const char *name)
Initialize the coroutine for the CoroutineScheduler, set it to Yielding state, and add it to the link...