1- # User Guide
1+ # AceRoutine User Guide
22
33See the [ README.md] ( README.md ) for installation instructions and other
44background information. This document describes how to use the library once it
55is installed.
66
7- ** Version** : 1.2 (2020-11-10 )
7+ ** Version** : 1.2.1 (2020-11-12 )
88
99** Table of Contents**
1010
1111* [ Coroutine Setup] ( #Setup )
12- * [ Include Header and Namespace] ( #Include )
12+ * [ Include Header and Namespace] ( #IncludeHeader )
1313 * [ Macros] ( #Macros )
1414 * [ Overall Structure] ( #OverallStructure )
1515 * [ Coroutine Class] ( #CoroutineClass )
@@ -26,10 +26,7 @@ is installed.
2626 * [ While Loops] ( #WhileLoops )
2727 * [ Forever Loops] ( #ForeverLoops )
2828 * [ Macros As Statements] ( #MacrosAsStatements )
29- * [ Coroutine Interactions] ( #CoroutineInteractions )
30- * [ No Nested Loop Macro] ( #NoNestedLoop )
31- * [ No Delegation to Regular Functions] ( #NoDelegation )
32- * [ Chaining Coroutines] ( #Chaining )
29+ * [ Chaining Coroutines] ( #ChainingCoroutines )
3330* [ Running and Scheduling] ( #RunningAndScheduling )
3431 * [ Manual Scheduling] ( #ManualScheduling )
3532 * [ CoroutineScheduler] ( #CoroutineScheduler )
@@ -38,19 +35,22 @@ is installed.
3835 * [ Reset Coroutine] ( #Reset )
3936 * [ Coroutine States] ( #States )
4037* [ Customizing] ( #Customizing )
41- * [ Custom Coroutines] ( #Custom )
42- * [ Manual Coroutines] ( #Manual )
38+ * [ Custom Coroutines] ( #CustomCoroutines )
39+ * [ Manual Coroutines] ( #ManualCoroutines )
4340* [ Coroutine Communication] ( #Communication )
4441 * [ Instance Variables] ( #InstanceVariables )
4542 * [ Channels (Experimental)] ( #Channels )
4643* [ Miscellaneous] ( #Miscellaneous )
4744 * [ External Coroutines] ( #External )
4845 * [ Functors] ( #Functors )
46+ * [ Bugs and Limitations] ( #BugsAndLimitations )
47+ * [ No Nested LOOP Macro] ( #NoNestedLoop )
48+ * [ No Delegation to Regular Functions] ( #NoDelegation )
4949
5050<a name =" Setup " ></a >
5151## Coroutine Setup
5252
53- <a name =" Include " ></a >
53+ <a name =" IncludeHeader " ></a >
5454### Include Header and Namespace
5555
5656Only a single header file ` AceRoutine.h ` is required to use this library.
@@ -191,7 +191,7 @@ subclasses. There are 2 recommended ways of creating coroutines:
191191* Manually subclassing the ` Coroutine ` class.
192192
193193(The third option is useful mostly for unit testing purposes, and is explained
194- later in the [ Custom Coroutines] ( #Custom ) section below.)
194+ later in the [ Custom Coroutines] ( #CustomCoroutines ) section below.)
195195
196196** Using COROUTINE() Macro**
197197
@@ -260,7 +260,7 @@ Since we are creating 2 instances of the `MyCoroutine` class, we call the
260260the constructor.
261261
262262For more details on manual Coroutine instances, see the
263- [Manual Coroutines](#Manual ) section below.
263+ [Manual Coroutines](#ManualCoroutines ) section below.
264264
265265<a name="CoroutineBody"></a>
266266## Coroutine Body
@@ -622,68 +622,14 @@ example, the following is allowed:
622622 ...
623623```
624624
625- <a name =" CoroutineInteractions " ></a >
626- ## Coroutine Interactions
627-
628- Here are some potentially surprising ways that certain macros or Coroutine
629- features interact with each other inside the ` runCoroutine() ` method.
630-
631- <a name =" NoNestedLoop " ></a >
632- ### No Nested Loop Macro
633-
634- The ` COROUTINE_LOOP() ` macro cannot be nested. In other words, the following is
635- ** not** allowed:
636-
637- ``` C++
638- COROUTINE (routine) {
639- COROUTINE_LOOP() {
640- ...
641- if (condition) {
642- COROUTINE_LOOP() { // <----- NOT ALLOWED
643- ...
644- COROUTINE_YIELD();
645- }
646- }
647- COROUTINE_YIELD();
648- }
649- }
650- ```
651-
652- <a name="NoDelegation"></a>
653- ### No Delegation to Regular Functions
654-
655- Coroutines macros inside the `runCoroutine()` **cannot** be delegated to another
656- C/C++ function, even though this becomes tempting when the `runCoroutine()`
657- implementation becomes complex. In other words, if you call another function
658- from within the `runCoroutine()`, you cannot use the various `COROUTINE_XXX()`
659- macros inside the delegated function. The macros were designed to trigger a
660- compiler error in most cases, but this is not guaranteed:
661-
662- ```C++
663- void doSomething() {
664- ...
665- COROUTINE_YIELD(); // <--- ***compiler error***
666- ...
667- }
668-
669- COROUTINE(cannotUseNestedMacros) {
670- COROUTINE_LOOP() {
671- if (condition) {
672- doSomething(); // <--- doesn't work
673- } else {
674- COROUTINE_YIELD();
675- }
676- }
677- }
678- ```
679-
680- <a name =" Chaining " ></a >
625+ <a name =" ChainingCoroutines " ></a >
681626### Chaining Coroutines
682627
683628Coroutines can be chained, in other words, the ` runCoroutine() ` of one coroutine
684629* can* explicitly call the ` runCoroutine() ` of another coroutine.
685630
686- I have found it useful to chain coroutines when using the ** Manual Coroutines**
631+ I have found it useful to chain coroutines when using the [ Manual
632+ Coroutines] ( #ManualCoroutines )
687633described in the section below. The ability to chain coroutines allows us to
688634implement a [ Decorator
689635Pattern] ( https://en.wikipedia.org/wiki/Decorator_pattern ) , also known as "a
@@ -784,6 +730,7 @@ in the global `loop()` method, like this:
784730``` C++
785731void setup () {
786732 ...
733+ myRoutine.setupCoroutine(F("myRoutine"));
787734 CoroutineScheduler::setup ();
788735}
789736
@@ -797,6 +744,11 @@ coroutines that are managed by the scheduler. Each call to
797744` CoroutineScheduler::loop() ` executes one coroutine in that list in a simple
798745round-robin scheduling algorithm.
799746
747+ If you are manually subclassing the ` Coroutine ` class to create your own
748+ [ Manual Coroutines] ( #ManualCoroutines ) , you must call the
749+ ` Coroutine::setupCoroutine() ` method in the global ` setup() ` so that the
750+ coroutine instance is added to the ` CoroutineScheduler ` .
751+
800752Prior to v1.2, the initial ordering was sorted by the ` Coroutine::getName() ` .
801753And calling ` suspend() ` would remove the coroutine from the internal list
802754of coroutines, and ` resume() ` would add the the coroutine back into the list.
@@ -966,7 +918,7 @@ COROUTINE(doSomethingElse) {
966918<a name="Customizing"></a>
967919## Customizing
968920
969- <a name="Custom "></a>
921+ <a name="CustomCoroutines "></a>
970922### Custom Coroutines (Not Recommended)
971923
972924All coroutines are instances of the `Coroutine` class, or one of its subclasses.
@@ -1003,7 +955,7 @@ where I have found this feature to be useful is in writing the
1003955situation, I suspect that the ** Manual Coroutines** section described in
1004956below will be more useful and easier to understand.
1005957
1006- <a name =" Manual " ></a >
958+ <a name =" ManualCoroutines " ></a >
1007959### Manual Coroutines (Recommended)
1008960
1009961A manual coroutine is a custom coroutine whose body of the coroutine (i.e
@@ -1083,6 +1035,8 @@ Some examples of manual coroutines:
10831035 [ BlinkSlowFastRoutine] ( examples/BlinkSlowFastRoutine )
10841036* [ HelloManualCoroutine] ( examples/HelloManualCoroutine ) which shows the same
10851037 functionality as [ HelloCoroutine] ( examples/HelloCoroutine ) .
1038+ * [ SoundManager] ( examples/SoundManager ) which uses both the automatic coroutine
1039+ defined by ` COROUTINE() ` macro and an explicitly subclasses manual coroutine.
10861040
10871041<a name="Communication"></a >
10881042## Coroutine Communication
@@ -1393,3 +1347,55 @@ C++ allows the creation of objects that look syntactically like functions.
13931347by defining the `operator()` method on the class. I have not defined this method
13941348in the `Coroutine` class because I have not found a use-case for it. However, if
13951349someone can demonstrate a compelling use-case, then I would be happy to add it.
1350+
1351+ <a name="BugsAndLimitations"></a>
1352+ ## Bugs and Limitations
1353+
1354+ <a name="NoNestedLoop"></a>
1355+ ### No Nested LOOP Macro
1356+
1357+ The `COROUTINE_LOOP()` macro cannot be nested. In other words, the following is
1358+ **not** allowed:
1359+
1360+ ```C++
1361+ COROUTINE(routine) {
1362+ COROUTINE_LOOP() {
1363+ ...
1364+ if (condition) {
1365+ COROUTINE_LOOP() { // <----- NOT ALLOWED
1366+ ...
1367+ COROUTINE_YIELD();
1368+ }
1369+ }
1370+ COROUTINE_YIELD();
1371+ }
1372+ }
1373+ ```
1374+
1375+ <a name="NoDelegation"></a >
1376+ ### No Delegation to Regular Functions
1377+
1378+ Coroutines macros inside the ` runCoroutine() ` ** cannot** be delegated to another
1379+ C/C++ function, even though this becomes tempting when the ` runCoroutine() `
1380+ implementation becomes complex. In other words, if you call another function
1381+ from within the ` runCoroutine() ` , you cannot use the various ` COROUTINE_XXX() `
1382+ macros inside the delegated function. The macros were designed to trigger a
1383+ compiler error in most cases, but this is not guaranteed:
1384+
1385+ ``` C++
1386+ void doSomething () {
1387+ ...
1388+ COROUTINE_YIELD (); // <--- *** compiler error***
1389+ ...
1390+ }
1391+
1392+ COROUTINE (cannotUseNestedMacros) {
1393+ COROUTINE_LOOP() {
1394+ if (condition) {
1395+ doSomething(); // <--- doesn't work
1396+ } else {
1397+ COROUTINE_YIELD();
1398+ }
1399+ }
1400+ }
1401+ ```
0 commit comments