AceRoutine
0.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 | |
Coroutine ** | getNext () |
Return the next pointer as a pointer to the pointer, similar to getRoot(). More... | |
const FCString & | getName () const |
Human-readable name of the coroutine. More... | |
virtual int | runCoroutine ()=0 |
The body of the coroutine. More... | |
virtual unsigned long | millis () const |
Returns the current millisecond clock. 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... | |
bool | isDelayExpired () |
Check if delay time is over. More... | |
bool | isSuspended () const |
The coroutine was suspended with a call to suspend(). More... | |
bool | isYielding () const |
The coroutine returned using COROUTINE_YIELD(). More... | |
bool | isDelaying () const |
The coroutine returned using COROUTINE_DELAY(). More... | |
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 *name) |
Initialize the coroutine for the CoroutineScheduler, set it to Yielding state, and add it to the linked list of coroutines. More... | |
void | setupCoroutine (const __FlashStringHelper *name) |
Same as setupCoroutine(const char*) except using flash string type. More... | |
Static Public Member Functions | |
static Coroutine ** | getRoot () |
Get the pointer to the root pointer. 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 | |
Coroutine () | |
Constructor. More... | |
Status | getStatus () const |
Return the status of the coroutine. More... | |
void | statusPrintTo (Print &printer) |
Print the human-readable string of the Status. More... | |
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. More... | |
void | setYielding () |
Set the kStatusDelaying state. More... | |
void | setDelaying () |
Set the kStatusDelaying state. More... | |
void | setDelay (uint16_t delayMillisDuration) |
Configure the delay timer. More... | |
void | setEnding () |
Set the kStatusEnding state. More... | |
void | setTerminated () |
Set status to indicate that the Coroutine has been removed from the Scheduler queue. 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. More... | |
static const Status | kStatusDelaying = 2 |
Coroutine returned using the COROUTINE_DELAY() statement. More... | |
static const Status | kStatusRunning = 3 |
Coroutine is currenly running. More... | |
static const Status | kStatusEnding = 4 |
Coroutine executed the COROUTINE_END() statement. More... | |
static const Status | kStatusTerminated = 5 |
Coroutine has ended and no longer in the scheduler queue. More... | |
Friends | |
class | CoroutineScheduler |
class | ::StatusStringTest |
Base class of all coroutines.
The actual coroutine code is an implementation of the virtual runCoroutine() method.
Definition at line 271 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 446 of file Coroutine.h.
|
inlineprotected |
Constructor.
All subclasses are expected to call either setupCoroutine(const char*) or setupCoroutine(const __FlashStringHelper*) before the CoroutineScheduler is used. The COROUTINE() macro will automatically call setupCoroutine().
See comment in setupCoroutine(const __FlashStringHelper*) for reason why an setupCoroutine() function is used instead of chaining the name through the constructor.
Definition at line 481 of file Coroutine.h.
|
inline |
Human-readable name of the coroutine.
Definition at line 291 of file Coroutine.h.
|
inline |
Return the next pointer as a pointer to the pointer, similar to getRoot().
This makes it much easier to manipulate a singly-linked list. Also makes setNext() method unnecessary.
Definition at line 288 of file Coroutine.h.
|
static |
Get the pointer to the root pointer.
Implemented as a function static to fix the C++ static initialization problem, making it safe to use this in other static contexts.
Definition at line 34 of file Coroutine.cpp.
|
inlineprotected |
Return the status of the coroutine.
Used by the CoroutineScheduler.
Definition at line 484 of file Coroutine.h.
|
inline |
Check if delay time is over.
Definition at line 335 of file Coroutine.h.
|
inline |
The coroutine returned using COROUTINE_DELAY().
Definition at line 347 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 372 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 357 of file Coroutine.h.
|
inline |
The coroutine is currently running.
True only within the coroutine.
Definition at line 350 of file Coroutine.h.
|
inline |
The coroutine was suspended with a call to suspend().
Definition at line 341 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 365 of file Coroutine.h.
|
inline |
The coroutine returned using COROUTINE_YIELD().
Definition at line 344 of file Coroutine.h.
|
virtual |
Returns the current millisecond clock.
By default it returns the global millis() function from Arduino but can be overridden for testing.
Definition at line 68 of file Coroutine.cpp.
void ace_routine::Coroutine::resume | ( | ) |
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 52 of file Coroutine.cpp.
|
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.
Implemented in ace_routine::cli::CommandDispatcher, ace_routine::cli::CommandManager< BUF_SIZE, ARGV_SIZE >, and ace_routine::cli::StreamLineReader.
|
inlineprotected |
Configure the delay timer.
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 basically all real 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 524 of file Coroutine.h.
|
inlineprotected |
Set the kStatusDelaying state.
Definition at line 510 of file Coroutine.h.
|
inlineprotected |
Set the kStatusEnding state.
Definition at line 532 of file Coroutine.h.
|
inlineprotected |
Set the kStatusRunning state.
Definition at line 504 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 538 of file Coroutine.h.
|
inline |
Initialize the coroutine for the CoroutineScheduler, set it to Yielding state, and add it to the linked list of coroutines.
This method is called automatically by the COROUTINE() macro. It needs to be called manually when using coroutines which were manually created without using that COROUTINE() macro.
This method could have been named init() or setup() but since this class expected to be used as a mix-in class to create more complex classes which could have its own setup() methods, the longer name seemed more clear.
name | The name of the coroutine as a human-readable string. |
Definition at line 390 of file Coroutine.h.
|
inline |
Same as setupCoroutine(const char*) except using flash string type.
Normally, the name would be passed from the subclass into this parent class through constructor chaining. But if we try to do that with the F() string, the compiler complains because F() macros work only inside a function. Therefore, the COROUTINE() macro uses the setupCoroutine() method to pass the name of the coroutine.
The problem doesn't exist for a (const char*) but for consistency, I made both types of strings pass through the setupCoroutine() method instead of chaining the constructor.
Definition at line 409 of file Coroutine.h.
|
inlineprotected |
Set the kStatusDelaying state.
Definition at line 507 of file Coroutine.h.
|
inlineprotected |
Print the human-readable string of the Status.
Definition at line 487 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 returned using the COROUTINE_DELAY() statement.
Definition at line 460 of file Coroutine.h.
|
staticprotected |
Coroutine executed the COROUTINE_END() statement.
Definition at line 466 of file Coroutine.h.
|
staticprotected |
Coroutine is currenly running.
True only within the coroutine itself.
Definition at line 463 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 454 of file Coroutine.h.
|
staticprotected |
Coroutine has ended and no longer in the scheduler queue.
Definition at line 469 of file Coroutine.h.
|
staticprotected |
Coroutine returned using the COROUTINE_YIELD() statement.
Definition at line 457 of file Coroutine.h.