Files
mixly3-server/arduino-libs/arduino-cli/libraries/TaskScheduler-master/src/TaskSchedulerDeclarations.h

394 lines
16 KiB
C++

// Cooperative multitasking library for Arduino
// Copyright (c) 2015-2019 Anatoli Arkhipenko
#include <stddef.h>
#include <stdint.h>
#ifndef _TASKSCHEDULERDECLARATIONS_H_
#define _TASKSCHEDULERDECLARATIONS_H_
// ----------------------------------------
// The following "defines" control library functionality at compile time,
// and should be used in the main sketch depending on the functionality required
//
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
// #define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between runs if no callback methods were invoked during the pass
// #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
// #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
// #define _TASK_LTS_POINTER // Compile with support for local task storage pointer
// #define _TASK_PRIORITY // Support for layered scheduling priority
// #define _TASK_MICRO_RES // Support for microsecond resolution
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 ONLY)
// #define _TASK_DEBUG // Make all methods and variables public for debug purposes
// #define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
// #define _TASK_TIMEOUT // Support for overall task timeout
// #define _TASK_OO_CALLBACKS // Support for callbacks via inheritance
// #define _TASK_EXPOSE_CHAIN // Methods to access tasks in the task chain
// #define _TASK_SCHEDULING_OPTIONS // Support for multiple scheduling options
// #define _TASK_DEFINE_MILLIS // Force forward declaration of millis() and micros() "C" style
// #define _TASK_EXTERNAL_TIME // Custom millis() and micros() methods
// #define _TASK_THREAD_SAFE // Enable additional checking for thread safety
class Scheduler;
#define TASK_SCHEDULE 0 // default
#define TASK_SCHEDULE_NC 1 // schedule + no catch-ups (always in the future)
#define TASK_INTERVAL 2 // interval (always in the future)
#ifdef _TASK_DEBUG
#define _TASK_SCOPE public
#else
#define _TASK_SCOPE private
#endif
#define TASK_IMMEDIATE 0
#define TASK_FOREVER (-1)
#define TASK_ONCE 1
#ifdef _TASK_TIMEOUT
#define TASK_NOTIMEOUT 0
#endif
#ifdef _TASK_PRIORITY
extern Scheduler* iCurrentScheduler;
#endif // _TASK_PRIORITY
#ifdef _TASK_INLINE
#define INLINE inline
#else
#define INLINE
#endif
#ifdef _TASK_EXTERNAL_TIME
#define _task_millis() external_millis()
#define _task_micros() external_micros()
#endif // _TASK_EXTERNAL_TIME
#ifndef _TASK_MICRO_RES
#define TASK_MILLISECOND 1UL
#define TASK_SECOND 1000UL
#define TASK_MINUTE 60000UL
#define TASK_HOUR 3600000UL
#else
#define TASK_MILLISECOND 1000UL
#define TASK_SECOND 1000000UL
#define TASK_MINUTE 60000000UL
#define TASK_HOUR 3600000000UL
#endif // _TASK_MICRO_RES
#ifdef _TASK_STATUS_REQUEST
#define TASK_SR_OK 0
#define TASK_SR_ERROR (-1)
#define TASK_SR_TIMEOUT (-99)
#define _TASK_SR_NODELAY 1
#define _TASK_SR_DELAY 2
class Scheduler;
class StatusRequest {
friend class Scheduler;
public:
INLINE StatusRequest();
INLINE void setWaiting(unsigned int aCount = 1);
INLINE bool signal(int aStatus = 0);
INLINE void signalComplete(int aStatus = 0);
INLINE bool pending();
INLINE bool completed();
INLINE int getStatus();
INLINE int getCount();
#ifdef _TASK_TIMEOUT
INLINE void setTimeout(unsigned long aTimeout) { iTimeout = aTimeout; };
INLINE unsigned long getTimeout() { return iTimeout; };
INLINE void resetTimeout();
INLINE long untilTimeout();
#endif
_TASK_SCOPE:
unsigned int iCount; // number of statuses to wait for. waiting for more that 65000 events seems unreasonable: unsigned int should be sufficient
int iStatus; // status of the last completed request. negative = error; zero = OK; positive = OK with a specific status
#ifdef _TASK_TIMEOUT
unsigned long iTimeout; // Task overall timeout
unsigned long iStarttime; // millis at task start time
#endif // _TASK_TIMEOUT
};
#endif // _TASK_STATUS_REQUEST
#ifdef _TASK_STD_FUNCTION
#include <functional>
typedef std::function<void()> TaskCallback;
typedef std::function<void()> TaskOnDisable;
typedef std::function<bool()> TaskOnEnable;
#else
typedef void (*TaskCallback)();
typedef void (*TaskOnDisable)();
typedef bool (*TaskOnEnable)();
#endif // _TASK_STD_FUNCTION
#ifdef _TASK_SLEEP_ON_IDLE_RUN
typedef void (*SleepCallback)( unsigned long aDuration );
extern Scheduler* iSleepScheduler;
extern SleepCallback iSleepMethod;
#endif // _TASK_SLEEP_ON_IDLE_RUN
typedef struct {
bool enabled : 1; // indicates that task is enabled or not.
bool inonenable : 1; // indicates that task execution is inside OnEnable method (preventing infinite loops)
bool canceled : 1; // indication that tast has been canceled prior to normal end of all iterations or regular call to disable()
#ifdef _TASK_STATUS_REQUEST
uint8_t waiting : 2; // indication if task is waiting on the status request
#endif
#ifdef _TASK_TIMEOUT
bool timeout : 1; // indication if task timed out
#endif
} __task_status;
class Task {
friend class Scheduler;
public:
#ifdef _TASK_OO_CALLBACKS
INLINE Task(unsigned long aInterval=0, long aIterations=0, Scheduler* aScheduler=NULL, bool aEnable=false);
#else
INLINE Task(unsigned long aInterval=0, long aIterations=0, TaskCallback aCallback=NULL, Scheduler* aScheduler=NULL, bool aEnable=false, TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
#endif // _TASK_OO_CALLBACKS
#ifdef _TASK_STATUS_REQUEST
#ifdef _TASK_OO_CALLBACKS
// INLINE Task(Scheduler* aScheduler=NULL);
INLINE Task(Scheduler* aScheduler);
#else
// INLINE Task(TaskCallback aCallback=NULL, Scheduler* aScheduler=NULL, TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
INLINE Task(TaskCallback aCallback, Scheduler* aScheduler, TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
#endif // _TASK_OO_CALLBACKS
#endif // _TASK_STATUS_REQUEST
virtual INLINE ~Task();
#ifdef _TASK_TIMEOUT
INLINE void setTimeout(unsigned long aTimeout, bool aReset=false);
INLINE void resetTimeout();
INLINE unsigned long getTimeout();
INLINE long untilTimeout();
INLINE bool timedOut();
#endif
INLINE bool enable();
INLINE bool enableIfNot();
INLINE bool enableDelayed(unsigned long aDelay=0);
INLINE bool restart();
INLINE bool restartDelayed(unsigned long aDelay=0);
INLINE void delay(unsigned long aDelay=0);
INLINE void adjust(long aInterval);
INLINE void forceNextIteration();
INLINE bool disable();
INLINE void abort();
INLINE void cancel();
INLINE bool isEnabled();
INLINE bool canceled();
#ifdef _TASK_SCHEDULING_OPTIONS
INLINE unsigned int getSchedulingOption() { return iOption; }
INLINE void setSchedulingOption(unsigned int aOption) { iOption = aOption; }
#endif //_TASK_SCHEDULING_OPTIONS
#ifdef _TASK_OO_CALLBACKS
INLINE void set(unsigned long aInterval, long aIterations);
#else
INLINE void set(unsigned long aInterval, long aIterations, TaskCallback aCallback,TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
#endif // _TASK_OO_CALLBACKS
INLINE void setInterval(unsigned long aInterval);
INLINE unsigned long getInterval();
INLINE void setIterations(long aIterations);
INLINE long getIterations();
INLINE unsigned long getRunCounter() ;
#ifdef _TASK_OO_CALLBACKS
virtual INLINE bool Callback() =0; // return true if run was "productive - this will disable sleep on the idle run for next pass
virtual INLINE bool OnEnable(); // return true if task should be enabled, false if it should remain disabled
virtual INLINE void OnDisable();
#else
INLINE void setCallback(TaskCallback aCallback) ;
INLINE void setOnEnable(TaskOnEnable aCallback) ;
INLINE void setOnDisable(TaskOnDisable aCallback) ;
INLINE void yield(TaskCallback aCallback);
INLINE void yieldOnce(TaskCallback aCallback);
#endif // _TASK_OO_CALLBACKS
INLINE bool isFirstIteration() ;
INLINE bool isLastIteration() ;
#ifdef _TASK_TIMECRITICAL
INLINE long getOverrun() ;
INLINE long getStartDelay() ;
#endif // _TASK_TIMECRITICAL
#ifdef _TASK_STATUS_REQUEST
INLINE bool waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
INLINE bool waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
INLINE StatusRequest* getStatusRequest() ;
INLINE StatusRequest* getInternalStatusRequest() ;
#endif // _TASK_STATUS_REQUEST
#ifdef _TASK_WDT_IDS
INLINE void setId(unsigned int aID) ;
INLINE unsigned int getId() ;
INLINE void setControlPoint(unsigned int aPoint) ;
INLINE unsigned int getControlPoint() ;
#endif // _TASK_WDT_IDS
#ifdef _TASK_LTS_POINTER
INLINE void setLtsPointer(void *aPtr) ;
INLINE void* getLtsPointer() ;
#endif // _TASK_LTS_POINTER
#ifdef _TASK_EXPOSE_CHAIN
INLINE Task* getPreviousTask() { return iPrev; }; // pointer to the previous task in the chain, NULL if first or not set
INLINE Task* getNextTask() { return iNext; }; // pointer to the next task in the chain, NULL if last or not set
#endif // _TASK_EXPOSE_CHAIN
_TASK_SCOPE:
INLINE void reset();
volatile __task_status iStatus;
volatile unsigned long iInterval; // execution interval in milliseconds (or microseconds). 0 - immediate
volatile unsigned long iDelay; // actual delay until next execution (usually equal iInterval)
volatile unsigned long iPreviousMillis; // previous invocation time (millis). Next invocation = iPreviousMillis + iInterval. Delayed tasks will "catch up"
#ifdef _TASK_SCHEDULING_OPTIONS
unsigned int iOption; // scheduling option
#endif // _TASK_SCHEDULING_OPTIONS
#ifdef _TASK_TIMECRITICAL
volatile long iOverrun; // negative if task is "catching up" to it's schedule (next invocation time is already in the past)
volatile long iStartDelay; // actual execution of the task's callback method was delayed by this number of millis
#endif // _TASK_TIMECRITICAL
volatile long iIterations; // number of iterations left. 0 - last iteration. -1 - infinite iterations
long iSetIterations; // number of iterations originally requested (for restarts)
unsigned long iRunCounter; // current number of iteration (starting with 1). Resets on enable.
#ifndef _TASK_OO_CALLBACKS
TaskCallback iCallback; // pointer to the void callback method
TaskOnEnable iOnEnable; // pointer to the bool OnEnable callback method
TaskOnDisable iOnDisable; // pointer to the void OnDisable method
#endif // _TASK_OO_CALLBACKS
Task *iPrev, *iNext; // pointers to the previous and next tasks in the chain
Scheduler *iScheduler; // pointer to the current scheduler
#ifdef _TASK_STATUS_REQUEST
StatusRequest *iStatusRequest; // pointer to the status request task is or was waiting on
StatusRequest iMyStatusRequest; // internal Status request to let other tasks know of completion
#endif // _TASK_STATUS_REQUEST
#ifdef _TASK_WDT_IDS
unsigned int iTaskID; // task ID (for debugging and watchdog identification)
unsigned int iControlPoint; // current control point within the callback method. Reset to 0 by scheduler at the beginning of each pass
#endif // _TASK_WDT_IDS
#ifdef _TASK_LTS_POINTER
void *iLTS; // pointer to task's local storage. Needs to be recast to appropriate type (usually a struct).
#endif // _TASK_LTS_POINTER
#ifdef _TASK_TIMEOUT
unsigned long iTimeout; // Task overall timeout
unsigned long iStarttime; // millis at task start time
#endif // _TASK_TIMEOUT
#ifdef _TASK_THREAD_SAFE
volatile uint8_t iMutex; // a mutex to pause scheduling during chages to the task
#endif
};
class Scheduler {
friend class Task;
public:
INLINE Scheduler();
// ~Scheduler();
INLINE void init();
INLINE void addTask(Task& aTask);
INLINE void deleteTask(Task& aTask);
INLINE void pause() { iPaused = true; };
INLINE void resume() { iPaused = false; };
INLINE void enable() { iEnabled = true; };
INLINE void disable() { iEnabled = false; };
#ifdef _TASK_PRIORITY
INLINE void disableAll(bool aRecursive = true);
INLINE void enableAll(bool aRecursive = true);
INLINE void startNow(bool aRecursive = true); // reset ALL active tasks to immediate execution NOW.
#else
INLINE void disableAll();
INLINE void enableAll();
INLINE void startNow(); // reset ALL active tasks to immediate execution NOW.
#endif
INLINE bool execute(); // Returns true if none of the tasks' callback methods was invoked (true = idle run)
INLINE Task& currentTask() ; // DEPRICATED
INLINE Task* getCurrentTask() ; // Returns pointer to the currently active task
INLINE long timeUntilNextIteration(Task& aTask); // return number of ms until next iteration of a given Task
#ifdef _TASK_SLEEP_ON_IDLE_RUN
INLINE void allowSleep(bool aState = true);
INLINE void setSleepMethod( SleepCallback aCallback );
#endif // _TASK_SLEEP_ON_IDLE_RUN
#ifdef _TASK_LTS_POINTER
INLINE void* currentLts();
#endif // _TASK_LTS_POINTER
#ifdef _TASK_TIMECRITICAL
INLINE bool isOverrun();
INLINE void cpuLoadReset();
INLINE unsigned long getCpuLoadCycle(){ return iCPUCycle; };
INLINE unsigned long getCpuLoadIdle() { return iCPUIdle; };
INLINE unsigned long getCpuLoadTotal();
#endif // _TASK_TIMECRITICAL
#ifdef _TASK_PRIORITY
INLINE void setHighPriorityScheduler(Scheduler* aScheduler);
INLINE static Scheduler& currentScheduler() { return *(iCurrentScheduler); };
#endif // _TASK_PRIORITY
#ifdef _TASK_EXPOSE_CHAIN
INLINE Task* getFirstTask() { return iFirst; }; // pointer to the previous task in the chain, NULL if first or not set
INLINE Task* getLastTask() { return iLast; }; // pointer to the next task in the chain, NULL if last or not set
#endif // _TASK_EXPOSE_CHAIN
_TASK_SCOPE:
Task *iFirst, *iLast, *iCurrent; // pointers to first, last and current tasks in the chain
volatile bool iPaused, iEnabled;
#ifdef _TASK_SLEEP_ON_IDLE_RUN
bool iAllowSleep; // indication if putting MC to IDLE_SLEEP mode is allowed by the program at this time.
#endif // _TASK_SLEEP_ON_IDLE_RUN
#ifdef _TASK_PRIORITY
Scheduler* iHighPriority; // Pointer to a higher priority scheduler
#endif // _TASK_PRIORITY
#ifdef _TASK_TIMECRITICAL
unsigned long iCPUStart;
unsigned long iCPUCycle;
unsigned long iCPUIdle;
#endif // _TASK_TIMECRITICAL
};
#endif /* _TASKSCHEDULERDECLARATIONS_H_ */