AceRoutine
1.0
A low-memory, fast-switching, cooperative multitasking library using stackless coroutines on Arduino platforms.
|
All coroutines are instances of the Coroutine base class. More...
#include <stdint.h>
#include <Print.h>
#include "FCString.h"
Go to the source code of this file.
Classes | |
class | ace_routine::Coroutine |
Base class of all coroutines. More... | |
Macros | |
#define | COROUTINE(...) GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__) |
Create a Coroutine instance named 'name'. More... | |
#define | GET_COROUTINE(_1, _2, NAME, ...) NAME |
#define | COROUTINE1(name) |
#define | COROUTINE2(className, name) |
#define | EXTERN_COROUTINE(...) |
Create an extern reference to a coroutine that is defined in another .cpp file. More... | |
#define | GET_EXTERN_COROUTINE(_1, _2, NAME, ...) NAME |
#define | EXTERN_COROUTINE1(name) |
#define | EXTERN_COROUTINE2(className, name) |
#define | COROUTINE_BEGIN() |
Mark the beginning of a coroutine. More... | |
#define | COROUTINE_LOOP() |
Mark the beginning of a coroutine loop. More... | |
#define | COROUTINE_YIELD_INTERNAL() |
#define | COROUTINE_YIELD() |
Yield execution to another coroutine. More... | |
#define | COROUTINE_AWAIT(condition) |
Yield until condition is true, then execution continues. More... | |
#define | COROUTINE_DELAY(delayMillis) |
Yield for delayMillis. More... | |
#define | COROUTINE_DELAY_MICROS(delayMicros) |
Yield for delayMicros. More... | |
#define | COROUTINE_DELAY_SECONDS(delaySeconds) |
Yield for delaySeconds. More... | |
#define | COROUTINE_END() |
Mark the end of a coroutine. More... | |
Functions | |
unsigned long | ace_routine::internal::udiv1000 (unsigned long n) |
Approximate division by 1000. More... | |
All coroutines are instances of the Coroutine base class.
The COROUTINE() macro creates these instances, and registers them to automatically run when CoroutineScheduler::loop() is called.
Various macros use macro overloading to implement a 1-argument and a 2-argument version. See https://stackoverflow.com/questions/11761703 to description of how that works.
The computed goto is a GCC extension: https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html The noinline and noclone attributes make sure that label pointers are always the same. I'm not 100% sure they are needed here, but they don't seem to hurt.
Definition in file Coroutine.h.
#define COROUTINE | ( | ... | ) | GET_COROUTINE(__VA_ARGS__, COROUTINE2, COROUTINE1)(__VA_ARGS__) |
Create a Coroutine instance named 'name'.
Two forms are supported
The 1-argument form uses the Coroutine class as the base class of the coroutine. The 2-argument form uses the user-provided className which must be a subclass of Coroutine.
The code in {} following this macro becomes the body of the Coroutine::runCoroutine() method.
Definition at line 65 of file Coroutine.h.
#define COROUTINE1 | ( | name | ) |
Definition at line 70 of file Coroutine.h.
#define COROUTINE2 | ( | className, | |
name | |||
) |
Definition at line 80 of file Coroutine.h.
#define COROUTINE_AWAIT | ( | condition | ) |
Yield until condition is true, then execution continues.
This is functionally equivalent to:
but potentially slightly more efficient.
Definition at line 159 of file Coroutine.h.
#define COROUTINE_BEGIN | ( | ) |
Mark the beginning of a coroutine.
Definition at line 119 of file Coroutine.h.
#define COROUTINE_DELAY | ( | delayMillis | ) |
Yield for delayMillis.
A delayMillis of 0 is functionally equivalent to COROUTINE_YIELD(). To save memory, the delayMillis is stored as a uint16_t but the actual maximum is limited to 32767 millliseconds. See setDelayMillis() for the reason for this limitation.
If you need to wait for longer than that, use a for-loop to call COROUTINE_DELAY() as many times as necessary or use COROUTINE_DELAY_SECONDS().
This could have been implemented using COROUTINE_AWAIT() but this macro matches the global delay(millis) function already provided by the Arduino API. Also having a separate kStatusDelaying state allows the CoroutineScheduler to be slightly more efficient by avoiding the call to Coroutine::runCoroutine() if the delay has not expired.
Definition at line 184 of file Coroutine.h.
#define COROUTINE_DELAY_MICROS | ( | delayMicros | ) |
Yield for delayMicros.
Similiar to COROUTINE_DELAY(delayMillis).
Definition at line 195 of file Coroutine.h.
#define COROUTINE_DELAY_SECONDS | ( | delaySeconds | ) |
Yield for delaySeconds.
Similar to COROUTINE_DELAY(delayMillis).
Definition at line 206 of file Coroutine.h.
#define COROUTINE_END | ( | ) |
Mark the end of a coroutine.
Subsequent calls to Coroutine::runCoroutine() will do nothing.
Definition at line 220 of file Coroutine.h.
#define COROUTINE_LOOP | ( | ) |
Mark the beginning of a coroutine loop.
Can be used instead of COROUTINE_BEGIN() at the beginning of a Coroutine.
Definition at line 129 of file Coroutine.h.
#define COROUTINE_YIELD | ( | ) |
Yield execution to another coroutine.
Definition at line 142 of file Coroutine.h.
#define COROUTINE_YIELD_INTERNAL | ( | ) |
Definition at line 133 of file Coroutine.h.
#define EXTERN_COROUTINE | ( | ... | ) |
Create an extern reference to a coroutine that is defined in another .cpp file.
The extern reference is needed before it can be used. Two forms are supported:
Definition at line 98 of file Coroutine.h.
#define EXTERN_COROUTINE1 | ( | name | ) |
Definition at line 104 of file Coroutine.h.
#define EXTERN_COROUTINE2 | ( | className, | |
name | |||
) |
Definition at line 111 of file Coroutine.h.
|
inline |
Approximate division by 1000.
More accurate algorithms exist (see for example http://www.hackersdelight.org/divcMore.pdf) but I'm pretty sure that this good enough since we don't guarantee accurate timing of the COROUTINE_DELAY*() methods.
Definition at line 238 of file Coroutine.h.