AceRoutine
1.0.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
32 class AceRoutineTest_statusStrings;
65 #define COROUTINE(...) \
66 GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__)
68 #define GET_COROUTINE(_1, _2, NAME, ...) NAME
70 #define COROUTINE1(name) \
71 struct Coroutine_##name : ace_routine::Coroutine { \
73 int runCoroutine() override; \
75 Coroutine_##name :: Coroutine_##name() { \
76 setupCoroutine(F(#name)); \
78 int Coroutine_##name :: runCoroutine()
80 #define COROUTINE2(className, name) \
81 struct className##_##name : className { \
82 className##_##name(); \
83 int runCoroutine() override; \
85 className##_##name :: className##_##name() { \
86 setupCoroutine(F(#name)); \
88 int className##_##name :: runCoroutine()
98 #define EXTERN_COROUTINE(...) \
99 GET_EXTERN_COROUTINE(\
100 __VA_ARGS__, EXTERN_COROUTINE2, EXTERN_COROUTINE1)(__VA_ARGS__)
102 #define GET_EXTERN_COROUTINE(_1, _2, NAME, ...) NAME
104 #define EXTERN_COROUTINE1(name) \
105 struct Coroutine_##name : ace_routine::Coroutine { \
106 Coroutine_##name(); \
107 int runCoroutine() override; \
109 extern Coroutine_##name name
111 #define EXTERN_COROUTINE2(className, name) \
112 struct className##_##name : className { \
113 className##_##name(); \
114 int runCoroutine() override; \
116 extern className##_##name name
119 #define COROUTINE_BEGIN() \
120 void* p = getJump(); \
121 if (p != nullptr) { \
129 #define COROUTINE_LOOP() \
133 #define COROUTINE_YIELD_INTERNAL() \
135 __label__ jumpLabel; \
136 setJump(&& jumpLabel); \
142 #define COROUTINE_YIELD() \
145 COROUTINE_YIELD_INTERNAL(); \
159 #define COROUTINE_AWAIT(condition) \
163 COROUTINE_YIELD_INTERNAL(); \
164 } while (!(condition)); \
184 #define COROUTINE_DELAY(delayMillis) \
186 setDelayMillis(delayMillis); \
189 COROUTINE_YIELD_INTERNAL(); \
190 } while (!isDelayExpired()); \
195 #define COROUTINE_DELAY_MICROS(delayMicros) \
197 setDelayMicros(delayMicros); \
200 COROUTINE_YIELD_INTERNAL(); \
201 } while (!isDelayExpired()); \
206 #define COROUTINE_DELAY_SECONDS(delaySeconds) \
208 setDelaySeconds(delaySeconds); \
211 COROUTINE_YIELD_INTERNAL(); \
212 } while (!isDelayExpired()); \
220 #define COROUTINE_END() \
222 __label__ jumpLabel; \
224 setJump(&& jumpLabel); \
229 namespace ace_routine {
244 unsigned long x = (n >> 8);
245 unsigned long y = (x >> 8);
246 unsigned long z = (y >> 8);
247 return (x >> 2) + 3 * (y >> 1) + 9 * z;
257 friend class ::AceRoutineTest_statusStrings;
334 switch (mDelayType) {
337 return elapsedMillis >= mDelayDuration;
341 return elapsedMicros >= mDelayDuration;
345 return elapsedSeconds >= mDelayDuration;
513 printer.print(sStatusStrings[mStatus]);
520 void setJump(
void* jumpPoint) { mJumpPoint = jumpPoint; }
562 mDelayDuration = (delayMillis >= UINT16_MAX / 2)
574 mDelayDuration = (delayMicros >= UINT16_MAX / 2)
586 mDelayDuration = (delaySeconds >= UINT16_MAX / 2)
597 static const __FlashStringHelper*
const sStatusStrings[];
615 void* mJumpPoint =
nullptr;
618 uint16_t mDelayStart;
619 uint16_t mDelayDuration;
void setDelayMillis(uint16_t delayMillis)
Configure the delay timer for delayMillis.
Status getStatus() const
Return the status of the coroutine.
void suspend()
Suspend the coroutine at the next scheduler iteration.
void setRunning()
Set the kStatusRunning state.
void setEnding()
Set the kStatusEnding state.
const FCString & getName() const
Human-readable name of the coroutine.
static const uint8_t kDelayTypeSeconds
Delay using units of seconds.
void setupCoroutine(const __FlashStringHelper *name)
Same as setupCoroutine(const char*) except using flash string type.
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.
bool isDelayExpired()
Check if delay time is over.
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...
Coroutine ** getNext()
Return the next pointer as a pointer to the pointer, similar to getRoot().
A union of (const char*) and (const __FlashStringHelper*) with a discriminator.
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.
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.
void setYielding()
Set the kStatusDelaying state.
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().
static Coroutine ** getRoot()
Get the pointer to the root pointer.
unsigned long udiv1000(unsigned long n)
Approximate division by 1000.
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...