|
3 | 3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. |
4 | 4 | */ |
5 | 5 |
|
6 | | -#ifndef TASKMANAGER_IO_H |
7 | | -#define TASKMANAGER_IO_H |
| 6 | +#ifndef TASKMANAGER_COMPAT_H |
| 7 | +#define TASKMANAGER_COMPAT_H |
8 | 8 |
|
9 | | -#include "TaskPlatformDeps.h" |
10 | | -#include "TaskTypes.h" |
11 | | -#include "TaskBlock.h" |
| 9 | +// |
| 10 | +// Provides compatibility with old task manager if needed |
| 11 | +// |
| 12 | +#include "TaskManagerIO.h" |
12 | 13 |
|
13 | | -/** |
14 | | - * @file TaskManager.h |
15 | | - * |
16 | | - * Task manager is a simple co-routine style implementation for Arduino which supports scheduling work to be done |
17 | | - * at a given time, repeating tasks, interrupt marshalling and events. It is generally thread safe such that code |
18 | | - * outside of task manager can add, remove and manage tasks even while task manager is running. |
19 | | - * |
20 | | - * Note that you should never add tasks from a raw ISR, instead use task manager's marshalling of interrupts or |
21 | | - * use an event that triggers on the interrupt occurring. |
22 | | - * |
23 | | - * The API for this class is compatible across Arduino, ESP and mbed. It is mainly thread safe on tested platforms. |
24 | | - * |
25 | | - * Both Commercial and Community support for task manager are available from http://www.thecoderscorner.com |
26 | | - */ |
27 | | - |
28 | | -#ifdef IOA_USE_MBED |
29 | | -#include <cstdint> |
30 | | -/** MBED ONLY: This defines the yield function for mbed boards, as per framework on Arduino */ |
31 | | -void yield(); |
32 | | -/** MBED ONLY: This defines the millis function for mbed boards by using a timer, as per framework on Arduino */ |
33 | | -uint32_t millis(); |
34 | | -/** MBED ONLY: This defines the micros function to use the standard mbed us timer, as per framework on Arduino */ |
35 | | -uint32_t micros(); |
36 | | -#endif // IOA_USE_MBED |
37 | | - |
38 | | -/** |
39 | | - * the definition of an interrupt handler function, to be called back when an interrupt occurs. |
40 | | - */ |
41 | | -typedef void (*RawIntHandler)(); |
42 | | - |
43 | | -/** |
44 | | - * Definition of a function to be called back when an interrupt is detected, marshalled by task manager into a task. |
45 | | - * The pin that caused the interrupt is passed in the parameter on a best efforts basis. |
46 | | - * @param pin the pin on which the interrupt occurred (best efforts) |
47 | | - */ |
48 | | -typedef void (*InterruptFn)(pintype_t pin); |
49 | | - |
50 | | -/** |
51 | | - * Abstracts the method by which interrupts are registered on the platform. Generally speaking this is implemented by |
52 | | - * all IoAbstractionRef implementations, so having any abstraction means you already have one of these. You can either |
53 | | - * implement your own variant of this, or use IoAbstraction to do it for you. |
54 | | - * |
55 | | - * For example if using IoAbstraction then the IO object returned by internalDigitalIo() implements this. |
56 | | - */ |
57 | | -class InterruptAbstraction { |
58 | | -public: |
59 | | - /** |
60 | | - * Register an interrupt handler to a specific pin on the device, such that the interrupt handler function will |
61 | | - * be triggered when mode is true. Mode can be one of CHANGE, RISING, FALLING. |
62 | | - * @param pin the pin on the device to attach an interrupt to |
63 | | - * @param fn the raw interrupt ISR function |
64 | | - * @param mode either RISING, FALLING or CHANGE |
65 | | - */ |
66 | | - virtual void attachInterrupt(pintype_t pin, RawIntHandler fn, uint8_t mode) = 0; |
67 | | -}; |
68 | | - |
69 | | -#ifdef IOA_USE_ARDUINO |
70 | | -/** |
71 | | - * For Arduino devices when NOT using IoAbstraction, this is the minimum possible implementation that can call |
72 | | - * through to the Arduino platform ::attachInterrupt call. You can pass a pointer to one of these to the task manager |
73 | | - * interrupt functions. If you are using IoAbstraction, all IoAbstractionRef's implement InterruptAbstraction. |
74 | | - */ |
75 | | -class BasicArduinoInterruptAbstraction : public InterruptAbstraction { |
76 | | - void attachInterrupt(pintype_t pin, RawIntHandler fn, uint8_t mode) override { |
77 | | -#ifdef ARDUINO_MBED_MODE |
78 | | - ::attachInterrupt(pin, fn, (PinStatus)mode); |
79 | | -#else |
80 | | - ::attachInterrupt(pin, fn, mode); |
81 | | -#endif // ARDUINO_MBED_MODE |
82 | | - } |
83 | | -}; |
84 | | -#endif // IOA_USE_ARDUINO - Arduino Only |
85 | | - |
86 | | -/** |
87 | | - * TaskManager is a lightweight cooperative co-routine implementation for Arduino, it works by scheduling tasks to be |
88 | | - * done either immediately, or at a future point in time. It is quite efficient at scheduling tasks as internally tasks |
89 | | - * are arranged in time order in a linked list. Tasks can be provided as either a function to be called, or a class |
90 | | - * that implements the Executable interface. Tasks can be scheduled to run either ASAP, once, or repeated. |
91 | | - * |
92 | | - * Events can be added based on extensions of the BaseEvent class, these can be triggered outside of task manager and |
93 | | - * they can then "wake up" task manager, events can also be polled. In addition interrupts can be marshalled through |
94 | | - * task manager, any interrupt managed by task manager will be marshalled into a task. IE outside of an ISR. |
95 | | - * |
96 | | - * There is a globally defined variable called `taskManager` and you should attach this to your main loop. You can |
97 | | - * create other task managers on different threads if required. For most use cases, the class is thread safe. |
98 | | - */ |
99 | | -class TaskManager { |
100 | | -protected: |
101 | | - // the memory that holds all the tasks is an array of task blocks, allocated on demand |
102 | | - TaskBlock* volatile taskBlocks[DEFAULT_TASK_BLOCKS]; // task blocks never ever move in memory, they are not volatile but the pointer is |
103 | | - volatile taskid_t numberOfBlocks; // this holds the current number of blocks available. |
104 | | - |
105 | | - // here we have a linked list of tasks, this linked list is in time order, nearest task first. |
106 | | - tm_internal::TimerTaskAtomicPtr first; |
107 | | - |
108 | | - // interrupt handling variables, store the interrupt state and probable pin cause if applicable |
109 | | - volatile pintype_t lastInterruptTrigger; |
110 | | - volatile bool interrupted; |
111 | | - volatile InterruptFn interruptCallback; |
112 | | - |
113 | | - tm_internal::TmAtomicBool memLockerFlag; // memory and list operations are locked by this flag using the TmSpinLocker |
114 | | -public: |
115 | | - /** |
116 | | - * On all platforms there is a default instance of TaskManager called taskManager. You can create other instances |
117 | | - * that can run on other threads, for example to process long running tasks that should be processed separately. |
118 | | - */ |
119 | | - TaskManager(); |
120 | | - ~TaskManager(); |
121 | | - |
122 | | - /** |
123 | | - * Executes a task manager task as soon as possible. Useful to add work into task manager from another thread of |
124 | | - * execution. Shorthand for scheduleOnce(0, task); |
125 | | - * @param workToDo the work to be done |
126 | | - * @return the task ID that can be queried and cancelled. |
127 | | - */ |
128 | | - inline taskid_t execute(TimerFn workToDo) { |
129 | | - return scheduleOnce(0, workToDo); |
130 | | - } |
131 | | - |
132 | | - /** |
133 | | - * Executes a task manager task as soon as possible. Useful to add work into task manager from another thread of |
134 | | - * execution. Shorthand for scheduleOnce(0, task); |
135 | | - * @param execToDo the work to be done |
136 | | - * @param deleteWhenDone default to false, task manager will reclaim the memory when done with this executable. |
137 | | - * @return the task ID that can be queried and cancelled. |
138 | | - */ |
139 | | - inline taskid_t execute(Executable* execToDo, bool deleteWhenDone = false) { |
140 | | - return scheduleOnce(0, execToDo, TIME_MICROS, deleteWhenDone); |
141 | | - } |
142 | | - |
143 | | - /** |
144 | | - * Schedules a task for one shot execution in the timeframe provided. |
145 | | - * @param millis the time frame in which to schedule the task |
146 | | - * @param timerFunction the function to run at that time |
147 | | - * @param timeUnit defaults to TIME_MILLIS but can be any of the possible values. |
148 | | - */ |
149 | | - taskid_t scheduleOnce(uint32_t when, TimerFn timerFunction, TimerUnit timeUnit = TIME_MILLIS); |
150 | | - |
151 | | - /** |
152 | | - * Schedules a task for one shot execution in the timeframe provided calling back the exec |
153 | | - * function on the provided class extending Executable. |
154 | | - * @param millis the time frame in which to schedule the task |
155 | | - * @param execRef a reference to a class extending Executable |
156 | | - * @param timeUnit defaults to TIME_MILLIS but can be any of the possible values. |
157 | | - * @param deleteWhenDone default to false, task manager will reclaim the memory when done with this executable. |
158 | | - */ |
159 | | - taskid_t scheduleOnce(uint32_t when, Executable* execRef, TimerUnit timeUnit = TIME_MILLIS, bool deleteWhenDone = false); |
160 | | - |
161 | | - /** |
162 | | - * Schedules a task for repeated execution at the frequency provided. |
163 | | - * @param millis the frequency at which to execute |
164 | | - * @param timerFunction the function to run at that time |
165 | | - * @param timeUnit defaults to TIME_MILLIS but can be any of the possible values. |
166 | | - */ |
167 | | - taskid_t scheduleFixedRate(uint32_t when, TimerFn timerFunction, TimerUnit timeUnit = TIME_MILLIS); |
168 | | - |
169 | | - /** |
170 | | - * Schedules a task for repeated execution at the frequency provided calling back the exec |
171 | | - * method on the provided class extending Executable. |
172 | | - * @param millis the frequency at which to execute |
173 | | - * @param execRef a reference to a class extending Executable |
174 | | - * @param timeUnit defaults to TIME_MILLIS but can be any of the possible values. |
175 | | - * @param deleteWhenDone true if taskManager should call delete on the object when done, otherwise false. |
176 | | - */ |
177 | | - taskid_t scheduleFixedRate(uint32_t when, Executable* execRef, TimerUnit timeUnit = TIME_MILLIS, bool deleteWhenDone = false); |
178 | | - |
179 | | - /** |
180 | | - * Adds an event to task manager that can be triggered either once or can be repeated. See the |
181 | | - * BaseEvent interface for more details of the interaction with taskManager. |
182 | | - * @param eventToAdd the event that is added to task manager |
183 | | - * @param deleteWhenDone true if taskManager should call delete on the object when done, otherwise false. |
184 | | - */ |
185 | | - taskid_t registerEvent(BaseEvent* eventToAdd, bool deleteWhenDone = false); |
186 | | - |
187 | | - /** |
188 | | - * Generally used by the BaseEvent class in the markTriggeredAndNotify to indicate that at least |
189 | | - * one event has now triggered and needs to be evaluated. |
190 | | - */ |
191 | | - void triggerEvents() { |
192 | | - lastInterruptTrigger = 0xff; // 0xff is the shorthand for event trigger basically. |
193 | | - interrupted = true; |
194 | | - } |
195 | | - |
196 | | - /** |
197 | | - * Adds an interrupt that will be handled by task manager, such that it's marshalled into a task. |
198 | | - * This registers an interrupt with any IoAbstractionRef. |
199 | | - * @param ref the Interrupt abstraction (or IoAbstractionRef) that we want to register the interrupt for |
200 | | - * @param pin the pin upon which to register (on the IoDevice above) |
201 | | - * @param mode the mode in which to register, eg. CHANGE, RISING, FALLING |
202 | | - */ |
203 | | - void addInterrupt(InterruptAbstraction* interruptAbstraction, pintype_t pin, uint8_t mode); |
204 | | - |
205 | | - /** |
206 | | - * Sets the interrupt callback to be used when an interrupt is signalled. Note that you will be |
207 | | - * called back by task manager, and you are safe to use any variables as normal. Task manager |
208 | | - * marshalls the interrupt for you. |
209 | | - * @param handler the interrupt handler |
210 | | - */ |
211 | | - void setInterruptCallback(InterruptFn handler); |
212 | | - |
213 | | - /** |
214 | | - * Stop a task from executing or cancel it from executing again if it is a repeating task |
215 | | - * @param task the task ID returned from the schedule call |
216 | | - */ |
217 | | - void cancelTask(taskid_t task); |
218 | | - |
219 | | - /** |
220 | | - * Use instead of delays or wait loops inside code that needs to perform timing functions. It will |
221 | | - * not call back until at least `micros` time has passed. |
222 | | - * @param micros the number of microseconds to wait. |
223 | | - */ |
224 | | - virtual void yieldForMicros(uint32_t micros); |
225 | | - |
226 | | - /** |
227 | | - * This should be called in the loop() method of your sketch, ensure that your loop method does |
228 | | - * not do anything that will unduly delay calling this method. |
229 | | - */ |
230 | | - void runLoop(); |
231 | | - |
232 | | - /** |
233 | | - * Used internally by the interrupt handlers to tell task manager an interrupt is waiting. Not for external use. |
234 | | - */ |
235 | | - static void markInterrupted(pintype_t interruptNo); |
236 | | - |
237 | | - /** |
238 | | - * Reset the task manager such that all current tasks are cleared, back to power on state. |
239 | | - */ |
240 | | - void reset() { |
241 | | - // all the slots should be cleared |
242 | | - for(taskid_t i =0; i<numberOfBlocks; i++) { |
243 | | - taskBlocks[i]->clearAll(); |
244 | | - } |
245 | | - // the queue must be completely cleared too. |
246 | | - tm_internal::atomicWritePtr(&first, nullptr); |
247 | | - } |
248 | | - |
249 | | - /** |
250 | | - * This method fills slotData with the current running conditions of each available task slot. |
251 | | - * Useful for debugging purposes, where each task the . |
252 | | - * Key: |
253 | | - * * 'R' repeating task ('r' when currently running) |
254 | | - * * 'U' one shot task ('u' when currently running) |
255 | | - * * 'F' free slot (should never be 'f') |
256 | | - * @param slotData the char array to fill in with task information. Must be as long as number of tasks + 1. |
257 | | - * @param slotDataSize the size of the array passed in (normally using sizeof). |
258 | | - */ |
259 | | - char* checkAvailableSlots(char* slotData, size_t slotDataSize) const; |
260 | | - |
261 | | - /** |
262 | | - * Gets the first task in the run queue. Not often useful outside of testing. |
263 | | - */ |
264 | | - TimerTask* getFirstTask() { |
265 | | - return tm_internal::atomicReadPtr(&first); |
266 | | - } |
267 | | - |
268 | | - /** |
269 | | - * Gets the underlying TimerTask variable associated with this task ID. |
270 | | - * @param task the task's ID |
271 | | - * @return the task or nullptr. |
272 | | - */ |
273 | | - TimerTask* getTask(taskid_t task); |
274 | | - |
275 | | - /** |
276 | | - * Gets the number of microseconds as an unsigned long to the next task execution. |
277 | | - * To convert to milliseconds: divide by 1000, to seconds divide by 1,000,000. |
278 | | - * @return the microseconds from now to next execution |
279 | | - */ |
280 | | - uint32_t microsToNextTask() { |
281 | | - auto maybeTask = tm_internal::atomicReadPtr(&first); |
282 | | - if(maybeTask == nullptr) return 600 * 1000000U; // wait for 10 minutes if there's nothing to do |
283 | | - else return maybeTask->microsFromNow(); |
284 | | - } |
285 | | -private: |
286 | | - /** |
287 | | - * Finds and allocates the next free task, once this returns a task will either have been allocated, making task |
288 | | - * manager storage bigger if needed, or it will return TASKMGR_INVALIDID otherwise. |
289 | | - * @return either a taskID or TASKMGR_INVALIDID if a slot could not be allocated |
290 | | - */ |
291 | | - taskid_t findFreeTask(); |
292 | | - |
293 | | - /** |
294 | | - * Removes an item from the task queue, so it is no longer in the run linked list. Note that there is a certain |
295 | | - * amount of concurrency and it's possible that this may coincide with the task running. |
296 | | - * |
297 | | - * Thread safety: Must only be called on the queue |
298 | | - * @param task the task to remove |
299 | | - */ |
300 | | - void removeFromQueue(TimerTask* task); |
301 | | - |
302 | | - /** |
303 | | - * Puts an item into the queue in time order, so the first to execute is at the top of the list. |
304 | | - * @param tm the task to be added. |
305 | | - */ |
306 | | - void putItemIntoQueue(TimerTask* tm); |
307 | | - |
308 | | - /** |
309 | | - * When an interrupt occurs, this goes through all active tasks |
310 | | - */ |
311 | | - void dealWithInterrupt(); |
312 | | -}; |
313 | | - |
314 | | -/** the global task manager, this would normally be associated with the main runLoop. */ |
315 | | -extern TaskManager taskManager; |
316 | | - |
317 | | -#endif //TASKMANAGER_IO_H |
| 14 | +#endif //TASKMANAGER_COMPAT_H |
0 commit comments