AceRoutine
1.4.2
A low-memory, fast-switching, cooperative multitasking library using stackless coroutines on Arduino platforms.
|
Base class of all coroutines. More...
#include <Coroutine.h>
Public Member Functions | |
virtual int | runCoroutine ()=0 |
The body of the coroutine. More... | |
virtual void | setupCoroutine () |
Perform coroutine initialization. More... | |
void | suspend () |
Suspend the coroutine at the next scheduler iteration. More... | |
void | resume () |
Add a Suspended coroutine into the head of the scheduler linked list, and change the state to Yielding. More... | |
void | reset () |
Reset the coroutine to its initial state. More... | |
bool | isDelayExpired () const |
Check if delay millis time is over. | |
bool | isDelayMicrosExpired () const |
Check if delay micros time is over. | |
bool | isDelaySecondsExpired () const |
Check if delay seconds time is over. | |
bool | isSuspended () const |
The coroutine was suspended with a call to suspend(). | |
bool | isYielding () const |
The coroutine returned using COROUTINE_YIELD(). | |
bool | isDelaying () const |
The coroutine returned using COROUTINE_DELAY(). | |
bool | isRunning () const |
The coroutine is currently running. More... | |
bool | isEnding () const |
The coroutine returned using COROUTINE_END(). More... | |
bool | isTerminated () const |
The coroutine was terminated by the scheduler with a call to setTerminated(). More... | |
bool | isDone () const |
The coroutine is either Ending or Terminated. More... | |
void | setupCoroutine (const char *) ACE_ROUTINE_DEPRECATED |
Deprecated method that does nothing. More... | |
void | setupCoroutine (const __FlashStringHelper *) ACE_ROUTINE_DEPRECATED |
Deprecated method that does nothing. More... | |
Protected Types | |
typedef uint8_t | Status |
The execution status of the coroutine, corresponding to the COROUTINE_YIELD(), COROUTINE_DELAY(), COROUTINE_AWAIT() and COROUTINE_END() macros. More... | |
Protected Member Functions | |
CoroutineTemplate () | |
Constructor. More... | |
~CoroutineTemplate ()=default | |
Destructor. More... | |
Status | getStatus () const |
Return the status of the coroutine. More... | |
void | statusPrintTo (Print &printer) |
Print the human-readable string of the Status. | |
void | setJump (void *jumpPoint) |
Pointer to label where execute will start on the next call to runCoroutine(). | |
void * | getJump () const |
Pointer to label where execute will start on the next call to runCoroutine(). | |
void | setRunning () |
Set the kStatusRunning state. | |
void | setYielding () |
Set the kStatusDelaying state. | |
void | setDelaying () |
Set the kStatusDelaying state. | |
void | setEnding () |
Set the kStatusEnding state. | |
void | setTerminated () |
Set status to indicate that the Coroutine has been removed from the Scheduler queue. More... | |
void | setDelayMillis (uint16_t delayMillis) |
Configure the delay timer for delayMillis. More... | |
void | setDelayMicros (uint16_t delayMicros) |
Configure the delay timer for delayMicros. More... | |
void | setDelaySeconds (uint16_t delaySeconds) |
Configure the delay timer for delaySeconds. More... | |
Static Protected Member Functions | |
static unsigned long | coroutineMillis () |
Returns the current millisecond clock. More... | |
static unsigned long | coroutineMicros () |
Returns the current microseconds clock. More... | |
static unsigned long | coroutineSeconds () |
Returns the current clock in unit of seconds, truncated to the lower 16-bits. More... | |
Protected Attributes | |
CoroutineTemplate * | mNext = nullptr |
Pointer to the next coroutine in a singly-linked list. | |
void * | mJumpPoint = nullptr |
Address of the label used by the computed-goto. | |
Status | mStatus = kStatusYielding |
Run-state of the coroutine. | |
uint16_t | mDelayStart |
Start time provided by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS(), or COROUTINE_DELAY_SECONDS(). More... | |
uint16_t | mDelayDuration |
Delay time specified by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS() or, COROUTINE_DELAY_SECONDS(). More... | |
Static Protected Attributes | |
static const Status | kStatusSuspended = 0 |
Coroutine has been suspended using suspend() and the scheduler should remove it from the queue upon the next iteration. More... | |
static const Status | kStatusYielding = 1 |
Coroutine returned using the COROUTINE_YIELD() statement. | |
static const Status | kStatusDelaying = 2 |
Coroutine returned using the COROUTINE_DELAY() statement. | |
static const Status | kStatusRunning = 3 |
Coroutine is currenly running. More... | |
static const Status | kStatusEnding = 4 |
Coroutine executed the COROUTINE_END() statement. | |
static const Status | kStatusTerminated = 5 |
Coroutine has ended and no longer in the scheduler queue. | |
Friends | |
class | CoroutineSchedulerTemplate< CoroutineTemplate< T_CLOCK > > |
class | ::AceRoutineTest_statusStrings |
class | ::SuspendTest_suspendAndResume |
Base class of all coroutines.
The actual coroutine code is an implementation of the virtual runCoroutine() method.
Definition at line 277 of file Coroutine.h.
|
protected |
The execution status of the coroutine, corresponding to the COROUTINE_YIELD(), COROUTINE_DELAY(), COROUTINE_AWAIT() and COROUTINE_END() macros.
The finite state diagram looks like this:
* Suspended * ^ ^ * / \ * / \ * v \ * Yielding Delaying * ^ ^ * \ / * \ / * \ / * v v * Running * | * | * v * Ending * | * | * v * Terminated *
Definition at line 466 of file Coroutine.h.
|
inlineprotected |
Constructor.
Automatically insert self into singly-linked list.
Definition at line 492 of file Coroutine.h.
|
protecteddefault |
Destructor.
Non-virtual.
A virtual destructor increases the flash memory consumption on 8-bit AVR processors by 500-600 bytes because it pulls in the free() and malloc() functions. On the 32-bit SAMD21, the flash memory increases by by about 350 bytes. On other 32-bit processors (STM32, ESP8266, ESP32, Teensy 3.2), the flash memory increase is modest, about 50-150 bytes.
Since a Coroutine is expected to be created statically, instead of the heap, a non-virtual destructor is good enough.
|
inlinestaticprotected |
Returns the current microseconds clock.
By default it returns the global micros() function from Arduino but can be overridden by providing a different T_CLOCK template parameter.
Definition at line 613 of file Coroutine.h.
|
inlinestaticprotected |
Returns the current millisecond clock.
By default it returns the global millis() function from Arduino but can be overridden by providing a different T_CLOCK template parameter.
Definition at line 604 of file Coroutine.h.
|
inlinestaticprotected |
Returns the current clock in unit of seconds, truncated to the lower 16-bits.
This is an approximation of (millis / 1000). It does not need to be perfectly accurate because COROUTINE_DELAY_SECONDS() is not guaranteed to be precise.
Definition at line 623 of file Coroutine.h.
|
inlineprotected |
Return the status of the coroutine.
Used by the CoroutineScheduler.
Definition at line 511 of file Coroutine.h.
|
inline |
The coroutine is either Ending or Terminated.
This method is recommended over isEnding() or isTerminated() because it works when the coroutine is executed either manually or through the CoroutineScheduler.
Definition at line 414 of file Coroutine.h.
|
inline |
The coroutine returned using COROUTINE_END().
In most cases, isDone() is recommended instead because it works when coroutines are executed manually or through the CoroutineScheduler.
Definition at line 399 of file Coroutine.h.
|
inline |
The coroutine is currently running.
True only within the coroutine.
Definition at line 392 of file Coroutine.h.
|
inline |
The coroutine was terminated by the scheduler with a call to setTerminated().
In most cases, isDone() should be used instead because it works when coroutines are executed manually or through the CoroutineScheudler.
Definition at line 407 of file Coroutine.h.
|
inline |
Reset the coroutine to its initial state.
Only the Coroutine base-class state is reset to the original state. If the subclass runCoroutine() uses any static variables (for example, a loop counter), you must reset those variables manually as well, since this library does not have any knowledge about them.
It is expected that this method will be called from outside the runCoroutine() method. If it is called within the method, I'm not sure what will happen. I think the coroutine will abandon the current continuation point, and start executing from the beginning of the Coroutine upon the next iteration.
Definition at line 356 of file Coroutine.h.
|
inline |
Add a Suspended coroutine into the head of the scheduler linked list, and change the state to Yielding.
If the coroutine is in any other state, this method does nothing. This method works only if the CoroutineScheduler::loop() is used.
Definition at line 332 of file Coroutine.h.
|
pure virtual |
The body of the coroutine.
The COROUTINE macro creates a subclass of this class and puts the body of the coroutine into this method.
|
inlineprotected |
Configure the delay timer for delayMicros.
Similar to seDelayMillis(), the maximum delay is 32767 micros.
Definition at line 575 of file Coroutine.h.
|
inlineprotected |
Configure the delay timer for delayMillis.
The maximum duration is set to (UINT16_MAX / 2) (i.e. 32767 milliseconds) if given a larger value. This makes the longest allowable time between two successive calls to isDelayExpired() for a given coroutine to be 32767 (UINT16_MAX - UINT16_MAX / 2 - 1) milliseconds, which should be long enough for all practical use-cases. (The '- 1' comes from an edge case where isDelayExpired() evaluates to be true in the CoroutineScheduler::runCoroutine() but becomes to be false in the COROUTINE_DELAY() macro inside Coroutine::runCoroutine()) because the clock increments by 1 millisecond.)
Definition at line 561 of file Coroutine.h.
|
inlineprotected |
Configure the delay timer for delaySeconds.
Similar to seDelayMillis(), the maximum delay is 32767 seconds.
Definition at line 589 of file Coroutine.h.
|
inlineprotected |
Set status to indicate that the Coroutine has been removed from the Scheduler queue.
Should be used only by the CoroutineScheduler.
Definition at line 546 of file Coroutine.h.
|
inlinevirtual |
Perform coroutine initialization.
This is intended to be called directly from the global setup()
function, or through the CoroutineScheduler::setupCoroutines()
method which should also be called from the global setup()
function.
If your coroutines do not override this method, hence do not need to perform any setup, then you should not call CoroutineScheduler::setupCoroutines()
to avoid consuming unnecessary flash memory. On AVR processors, each Coroutine::setupCoroutine()
seems to consume at least 50-60 bytes of flash memory overhead per coroutine. On 32-bit processors, the overhead seems to be only about 30-40 bytes per coroutine.
Definition at line 309 of file Coroutine.h.
|
inline |
Deprecated method that does nothing.
Starting v1.3, the setup into the singly-linked list is automatically performed by the constructor and this method no longer needs to be called manually. This method is retained for backwards compatibility.
Definition at line 432 of file Coroutine.h.
|
inline |
Deprecated method that does nothing.
Starting v1.3, the setup into the singly-linked list is automatically performed by the constructor and this method no longer needs to be called manually. This method is retained for backwards compatibility.
Definition at line 424 of file Coroutine.h.
|
inline |
Suspend the coroutine at the next scheduler iteration.
If the coroutine is already in the process of ending or is already terminated, then this method does nothing. A coroutine cannot use this method to suspend itself, it can only suspend some other coroutine. Currently, there is no ability for a coroutine to suspend itself, that would require the addition of a COROUTINE_SUSPEND() macro. Also, this method works only if the CoroutineScheduler::loop() is used because the suspend functionality is implemented by the CoroutineScheduler.
Definition at line 321 of file Coroutine.h.
|
staticprotected |
Coroutine is currenly running.
True only within the coroutine itself.
Definition at line 483 of file Coroutine.h.
|
staticprotected |
Coroutine has been suspended using suspend() and the scheduler should remove it from the queue upon the next iteration.
We don't distinguish whether the coroutine is still in the queue or not with this status. We can add that later if we need to.
Definition at line 474 of file Coroutine.h.
|
protected |
Delay time specified by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS() or, COROUTINE_DELAY_SECONDS().
The unit of this number is context dependent, milliseconds, microseconds, or seconds.
Definition at line 686 of file Coroutine.h.
|
protected |
Start time provided by COROUTINE_DELAY(), COROUTINE_DELAY_MICROS(), or COROUTINE_DELAY_SECONDS().
The unit of this number is context dependent, milliseconds, microseconds, or seconds.
Definition at line 679 of file Coroutine.h.