AceRoutine
1.2.1
A low-memory, fast-switching, cooperative multitasking library using stackless coroutines on Arduino platforms.
|
#include <stdint.h>
#include <Print.h>
#include <AceCommon.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 |
Internal helper macro to allow overloading of the COROUTINE() macro. | |
#define | COROUTINE1(name) |
Implement the 1-argument COROUTINE() macro. More... | |
#define | COROUTINE2(className, name) |
Implement the 2-argument COROUTINE() macro. More... | |
#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 |
Internal helper macro to allow overloading of the EXTERN_COROUTINE() macro. | |
#define | EXTERN_COROUTINE1(name) |
Implement the 1-argument EXTERN_COROUTINE() macro. More... | |
#define | EXTERN_COROUTINE2(className, name) |
Implement the 2-argument EXTERN_COROUTINE() macro. More... | |
#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() |
Implement the common logic for COROUTINE_YIELD(), COROUTINE_AWAIT(), COROUTINE_DELAY(), COROUTINE_DELAY_SECONDS(), and COROUTINE_DELAY_MICROS(). More... | |
#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... | |
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 66 of file Coroutine.h.
#define COROUTINE1 | ( | name | ) |
Implement the 1-argument COROUTINE() macro.
Definition at line 73 of file Coroutine.h.
#define COROUTINE2 | ( | className, | |
name | |||
) |
Implement the 2-argument COROUTINE() macro.
Definition at line 84 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 172 of file Coroutine.h.
#define COROUTINE_BEGIN | ( | ) |
Mark the beginning of a coroutine.
Definition at line 128 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 197 of file Coroutine.h.
#define COROUTINE_DELAY_MICROS | ( | delayMicros | ) |
Yield for delayMicros.
Similiar to COROUTINE_DELAY(delayMillis).
Definition at line 208 of file Coroutine.h.
#define COROUTINE_DELAY_SECONDS | ( | delaySeconds | ) |
Yield for delaySeconds.
Similar to COROUTINE_DELAY(delayMillis).
The accuracy of the delay interval in units of seconds has at least 2 sources of errors, so you should not depend on this for perfectly accurate delays:
1) The current implementation uses the builtin millis() to infer the "seconds". The millis() function returns a value that overflows after 4,294,967.296 seconds. Therefore, the last inferred second just before overflowing contains only 0.296 seconds instead of a full second. A delay which straddles this overflow will return 0.704 seconds earlier than it should. 2) On microcontrollers without support for fast hardware integer division, (i.e. AVR, SAMD21, ESP8266), the division by 1000 is approximated using integer multiplications. The calculated value is off by a fraction of a percent from the correct value.
Definition at line 236 of file Coroutine.h.
#define COROUTINE_END | ( | ) |
Mark the end of a coroutine.
Subsequent calls to Coroutine::runCoroutine() will do nothing.
Definition at line 250 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 138 of file Coroutine.h.
#define COROUTINE_YIELD | ( | ) |
Yield execution to another coroutine.
Definition at line 155 of file Coroutine.h.
#define COROUTINE_YIELD_INTERNAL | ( | ) |
Implement the common logic for COROUTINE_YIELD(), COROUTINE_AWAIT(), COROUTINE_DELAY(), COROUTINE_DELAY_SECONDS(), and COROUTINE_DELAY_MICROS().
Definition at line 146 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 102 of file Coroutine.h.
#define EXTERN_COROUTINE1 | ( | name | ) |
Implement the 1-argument EXTERN_COROUTINE() macro.
Definition at line 112 of file Coroutine.h.
#define EXTERN_COROUTINE2 | ( | className, | |
name | |||
) |
Implement the 2-argument EXTERN_COROUTINE() macro.
Definition at line 120 of file Coroutine.h.