| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135 |
- /**
- * @file TaskSchedulerDeclarations.h
- * @brief Cooperative multitasking library for Arduino microcontrollers
- * @author Anatoli Arkhipenko
- * @version 4.0.0
- * @date 2015-2023
- * @copyright Copyright (c) 2015-2025 Anatoli Arkhipenko
- *
- * @details A lightweight implementation of cooperative multitasking (task scheduling) supporting:
- * - Periodic task execution, with dynamic execution period in milliseconds (default) or microseconds
- * - Number of iterations (limited or infinite number of iterations)
- * - Execution of tasks in the predefined sequence
- * - Dynamic change of task execution parameters (frequency, number of iterations, callback methods)
- * - Power saving via entering IDLE sleep mode when tasks are not scheduled to run
- * - Support for event-driven task invocation via Status Request object
- * - Support for task IDs and Control Points for error handling and watchdog timer
- * - Support for Local Task Storage pointer (allowing the use of same callback code for multiple tasks)
- * - Support for layered task prioritization
- * - Support for std::functions
- * - Overall task timeout
- * - Static and dynamic callback method binding
- *
- * Scheduling overhead: between 15 and 18 microseconds per scheduling pass (Arduino UNO rev 3 @ 16MHz clock, single scheduler w/o prioritization)
- */
- #ifndef _TASKSCHEDULERDECLARATIONS_H_
- #define _TASKSCHEDULERDECLARATIONS_H_
- // ----------------------------------------
- /**
- * @defgroup CompileTimeOptions Compile Time Options
- * @brief The following "defines" control library functionality at compile time,
- * and should be used in the main sketch depending on the functionality required
- * @{
- */
- /**
- * @def _TASK_TIMECRITICAL
- * @brief Enable monitoring scheduling overruns
- * @details Enables tracking when the current execution took place relative to when it was scheduled.
- * Provides getStartDelay() and getOverrun() methods for performance monitoring.
- */
- /**
- * @def _TASK_SLEEP_ON_IDLE_RUN
- * @brief Enable 1 ms SLEEP_IDLE powerdowns between runs if no callback methods were invoked during the pass
- * @details When enabled, the scheduler will place the processor into IDLE sleep mode for approximately 1 ms
- * after what is determined to be an "idle" pass. AVR boards only.
- */
- /**
- * @def _TASK_STATUS_REQUEST
- * @brief Compile with support for StatusRequest functionality
- * @details Enables triggering tasks on status change events in addition to time-based scheduling.
- * Allows tasks to wait on an event and signal event completion to each other.
- */
- /**
- * @def _TASK_WDT_IDS
- * @brief Compile with support for watchdog timer control points and task IDs
- * @details Each task can be assigned an ID and Control Points can be defined within tasks
- * for watchdog timer integration and error handling.
- */
- /**
- * @def _TASK_LTS_POINTER
- * @brief Compile with support for local task storage pointer
- * @details LTS is a generic (void*) pointer that can reference a variable or structure
- * specific to a particular task, allowing the same callback code for multiple tasks.
- */
- /**
- * @def _TASK_PRIORITY
- * @brief Support for layered scheduling priority
- * @details Enables task prioritization by creating several schedulers and organizing them in priority layers.
- * Higher priority tasks are evaluated more frequently.
- */
- /**
- * @def _TASK_MICRO_RES
- * @brief Support for microsecond resolution
- * @details Enables microsecond scheduling resolution instead of default millisecond resolution.
- * All time-relevant parameters will be treated as microseconds.
- */
- /**
- * @def _TASK_STD_FUNCTION
- * @brief Support for std::function (ESP8266/ESP32 ONLY)
- * @details Enables support for standard functions instead of function pointers for callbacks.
- */
- /**
- * @def _TASK_DEBUG
- * @brief Make all methods and variables public for debug purposes
- * @details Should not be used in production. Exposes all private and protected members as public.
- */
- /**
- * @def _TASK_INLINE
- * @brief Make all methods "inline"
- * @details Needed to support some multi-tab, multi-file implementations. Lets compiler optimize.
- */
- /**
- * @def _TASK_TIMEOUT
- * @brief Support for overall task timeout
- * @details Any task can be set to time out after a certain period, and timeout can be reset.
- * Can be used as an individual Task's watchdog timer.
- */
- /**
- * @def _TASK_OO_CALLBACKS
- * @brief Support for callbacks via inheritance
- * @details Useful for implementing Tasks as classes derived from the Task class.
- * Enables dynamic binding for object-oriented callback approach.
- */
- /**
- * @def _TASK_EXPOSE_CHAIN
- * @brief Methods to access tasks in the task chain
- * @details Provides access to scheduling chain methods and tasks on the chain.
- */
- /**
- * @def _TASK_SCHEDULING_OPTIONS
- * @brief Support for multiple scheduling options
- * @details Enables different task scheduling options like TASK_SCHEDULE, TASK_SCHEDULE_NC, and TASK_INTERVAL.
- */
- /**
- * @def _TASK_SELF_DESTRUCT
- * @brief Enable tasks to "self-destruct" after disable
- * @details Tasks can be set to automatically delete themselves when disabled.
- */
- /**
- * @def _TASK_TICKLESS
- * @brief Enable support for tickless sleep on FreeRTOS
- * @details Enables support for tickless sleep mode on FreeRTOS systems.
- */
- /**
- * @def _TASK_DO_NOT_YIELD
- * @brief Disable yield() method in execute() for ESP chips
- * @details Disables automatic yielding in the execute loop for ESP-based systems.
- */
- /**
- * @def _TASK_ISR_SUPPORT
- * @brief For ESP chips - place control methods in IRAM
- * @details Places critical control methods in IRAM for ESP8266/ESP32 interrupt support.
- */
- /**
- * @def _TASK_NON_ARDUINO
- * @brief For non-Arduino use
- * @details Enables compilation for non-Arduino environments.
- */
- /**
- * @def _TASK_HEADER_AND_CPP
- * @brief Compile CPP file (non-Arduino IDE platforms)
- * @details For non-Arduino IDE platforms that require explicit CPP compilation.
- */
- /**
- * @def _TASK_THREAD_SAFE
- * @brief Enable additional checking for thread safety
- * @details Uses an internal mutex to protect task scheduling methods from preemption.
- * Recommended for ESP32 and other MCUs running under preemptive schedulers like FreeRTOS.
- */
- /** @} */ // End of CompileTimeOptions group
- #ifdef _TASK_NON_ARDUINO
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdarg.h>
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <inttypes.h>
- #else
- #include <Arduino.h>
- #endif
- /**
- * @brief Forward declaration of Scheduler class
- */
- class Scheduler;
- /**
- * @defgroup SchedulingOptions Task Scheduling Options
- * @brief Constants defining different task scheduling behaviors
- * @{
- */
- /**
- * @def TASK_SCHEDULE
- * @brief Default scheduling option
- * @details Maintains the original schedule. Tasks may need to "catch up" if delayed.
- * If a task is scheduled to run every 10 seconds and starts at 9:00:00,
- * the scheduler will try to invoke tasks as close to 9:00:10, 9:00:20 as possible.
- */
- #define TASK_SCHEDULE 0
- /**
- * @def TASK_SCHEDULE_NC
- * @brief Schedule with no catch-ups (always in the future)
- * @details Similar to TASK_SCHEDULE but without "catch up". Tasks are invoked at the next
- * scheduled point, but the number of iterations may not be correct if delayed.
- */
- #define TASK_SCHEDULE_NC 1
- /**
- * @def TASK_INTERVAL
- * @brief Interval-based scheduling (always in the future)
- * @details Schedules the next invocation with priority to a "period". A task scheduled for
- * 9:00:00 with a 10-second interval that was actually invoked at 9:00:06 will be
- * scheduled for the next invocation at 9:00:16.
- */
- #define TASK_INTERVAL 2
- /** @} */ // End of SchedulingOptions group
- #ifdef _TASK_DEBUG
- #define _TASK_SCOPE public
- #else
- #define _TASK_SCOPE private
- #endif
- /**
- * @defgroup TaskIterationOptions Task Iteration Options
- * @brief Common options for task scheduling iterations
- * @{
- */
- /**
- * @def TASK_IMMEDIATE
- * @brief Task interval for immediate execution
- * @details When used as interval, causes task to execute immediately during next scheduling pass.
- */
- #define TASK_IMMEDIATE 0
- /**
- * @def TASK_FOREVER
- * @brief Task number of iterations for infinite execution
- * @details When used as iteration count, causes task to run indefinitely until explicitly disabled.
- */
- #define TASK_FOREVER (-1)
- /**
- * @def TASK_ONCE
- * @brief Task single iteration
- * @details When used as iteration count, causes task to run only once and then become disabled.
- */
- #define TASK_ONCE 1
- /** @} */ // End of TaskIterationOptions group
- /**
- * @defgroup IntervalNoDelayOptions Options for setIntervalNodelay() method
- * @brief Options controlling how interval changes are handled
- * @{
- */
- /**
- * @def TASK_INTERVAL_KEEP
- * @brief Keep current execution timing
- * @details Maintains the current execution schedule when changing interval.
- */
- #define TASK_INTERVAL_KEEP 0
- /**
- * @def TASK_INTERVAL_RECALC
- * @brief Recalculate execution timing
- * @details Recalculates the next execution time based on the new interval.
- */
- #define TASK_INTERVAL_RECALC 1
- /**
- * @def TASK_INTERVAL_RESET
- * @brief Reset execution timing
- * @details Resets the execution schedule to start from the current time.
- */
- #define TASK_INTERVAL_RESET 2
- /** @} */ // End of IntervalNoDelayOptions group
- /**
- * @defgroup TimeoutOptions Task Timeout Options
- * @brief Options for task timeout functionality
- * @{
- */
- #ifdef _TASK_TIMEOUT
- /**
- * @def TASK_NOTIMEOUT
- * @brief No timeout value
- * @details Used to indicate that a task should not have a timeout.
- */
- #define TASK_NOTIMEOUT 0
- #endif
- /** @} */ // End of TimeoutOptions group
- #ifdef _TASK_PRIORITY
- extern Scheduler* iCurrentScheduler;
- #endif // _TASK_PRIORITY
- #ifdef _TASK_INLINE
- #define __TASK_INLINE inline
- #else
- #define __TASK_INLINE
- #endif
- #ifdef _TASK_ISR_SUPPORT
- #if defined (ARDUINO_ARCH_ESP8266)
- #define __TASK_IRAM ICACHE_RAM_ATTR
- #endif
- #if defined (ARDUINO_ARCH_ESP32)
- #define __TASK_IRAM IRAM_ATTR
- #endif
- #endif
- #ifndef __TASK_IRAM
- #define __TASK_IRAM
- #endif
- /**
- * @defgroup TimeConstants Time Constants
- * @brief Predefined time constants for task intervals
- * @details Values are in milliseconds by default, or microseconds when _TASK_MICRO_RES is enabled
- * @{
- */
- #ifndef _TASK_MICRO_RES
- /**
- * @def TASK_MILLISECOND
- * @brief One millisecond interval
- */
- #define TASK_MILLISECOND 1UL
- /**
- * @def TASK_SECOND
- * @brief One second interval (1000 milliseconds)
- */
- #define TASK_SECOND 1000UL
- /**
- * @def TASK_MINUTE
- * @brief One minute interval (60000 milliseconds)
- */
- #define TASK_MINUTE 60000UL
- /**
- * @def TASK_HOUR
- * @brief One hour interval (3600000 milliseconds)
- */
- #define TASK_HOUR 3600000UL
- #else
- /**
- * @def TASK_MILLISECOND
- * @brief One millisecond interval (1000 microseconds)
- */
- #define TASK_MILLISECOND 1000UL
- /**
- * @def TASK_SECOND
- * @brief One second interval (1000000 microseconds)
- */
- #define TASK_SECOND 1000000UL
- /**
- * @def TASK_MINUTE
- * @brief One minute interval (60000000 microseconds)
- */
- #define TASK_MINUTE 60000000UL
- /**
- * @def TASK_HOUR
- * @brief One hour interval (3600000000 microseconds)
- */
- #define TASK_HOUR 3600000000UL
- #endif // _TASK_MICRO_RES
- /** @} */ // End of TimeConstants group
- #ifdef _TASK_TICKLESS
- /**
- * @defgroup NextRunStates Task Next Run State Definitions
- * @brief State flags for tickless operation next run scheduling
- *
- * These constants define the next execution state of tasks in tickless mode,
- * enabling power-efficient operation by categorizing when tasks need to run.
- * Used internally by the scheduler to optimize sleep/wake cycles and minimize
- * power consumption in battery-powered applications.
- *
- * @note Only available when _TASK_TICKLESS compile-time option is enabled
- * @see _TASK_TICKLESS
- * @{
- */
- /**
- * @brief Undefined next run state
- *
- * Indicates that the task's next execution time is not defined or has not
- * been calculated. This is typically an initial state or error condition
- * where the scheduler cannot determine when the task should next execute.
- *
- * Binary value: 0b0 (0)
- *
- * @note Used internally by tickless scheduler for state management
- * @see _TASK_TICKLESS
- * @since Version 3.0.0
- */
- #define _TASK_NEXTRUN_UNDEFINED 0b0
- /**
- * @brief Immediate next run state
- *
- * Indicates that the task should execute immediately on the next scheduler
- * pass, bypassing any timing delays. Used for tasks that have been triggered
- * by events, forced execution, or have reached their scheduled execution time.
- *
- * Binary value: 0b1 (1)
- *
- * @note In tickless mode, prevents the system from entering deep sleep
- * @see forceNextIteration(), _TASK_TICKLESS
- * @since Version 3.0.0
- */
- #define _TASK_NEXTRUN_IMMEDIATE 0b1
- /**
- * @brief Timed next run state
- *
- * Indicates that the task has a specific future execution time and should
- * wait until that time arrives. This enables the tickless scheduler to
- * calculate optimal sleep durations and enter power-saving modes until
- * the earliest task execution time.
- *
- * Hexadecimal value: 0x10 (16)
- *
- * @note Enables deep sleep optimization in tickless mode
- * @note Value deliberately different from other states for bit manipulation
- * @see _TASK_TICKLESS, getInterval(), delay()
- * @since Version 3.0.0
- */
- #define _TASK_NEXTRUN_TIMED 0x10
- /** @} */ // End of NextRunStates group
- #endif // _TASK_TICKLESS
- #ifdef _TASK_THREAD_SAFE
- /**
- * @enum _task_request_type_t
- * @brief Task request types for thread-safe operations
- *
- * @details This enum mirrors the Task class API for invocation via requestAction methods
- * when _TASK_THREAD_SAFE option is active. It provides a thread-safe way to execute
- * task control methods by placing requests on a queue that is processed during the
- * scheduler's execute() method.
- *
- * Each enum value corresponds to a specific Task method that can be called safely
- * from other threads or interrupt contexts. The scheduler processes these requests
- * atomically during its execution cycle.
- *
- * @note Only available when compiled with _TASK_THREAD_SAFE support.
- *
- * @see Scheduler::requestAction()
- */
- typedef enum {
- #ifdef _TASK_STATUS_REQUEST
- TASK_SR_REQUEST_SETWAITING, ///< Thread-safe StatusRequest::setWaiting()
- TASK_SR_REQUEST_SIGNAL, ///< Thread-safe StatusRequest::signal()
- TASK_SR_REQUEST_SIGNALCOMPLETE, ///< Thread-safe StatusRequest::signalComplete()
- #ifdef _TASK_TIMEOUT
- TASK_SR_REQUEST_SETTIMEOUT, ///< Thread-safe StatusRequest::setTimeout()
- TASK_SR_REQUEST_RESETTIMEOUT, ///< Thread-safe StatusRequest::resetTimeout()
- #endif // _TASK_TIMEOUT
- #endif // _TASK_STATUS_REQUEST
- #ifdef _TASK_LTS_POINTER
- TASK_REQUEST_SETLTSPOINTER, ///< Thread-safe Task::setLtsPointer()
- #endif
- #ifdef _TASK_SELF_DESTRUCT
- TASK_REQUEST_SETSELFDESTRUCT, ///< Thread-safe Task::setSelfDestruct()
- #endif // _TASK_SELF_DESTRUCT
- #ifdef _TASK_SCHEDULING_OPTIONS
- TASK_REQUEST_SETSCHEDULINGOPTION, ///< Thread-safe Task::setSchedulingOption()
- #endif // _TASK_SCHEDULING_OPTIONS
- #ifdef _TASK_TIMEOUT
- TASK_REQUEST_SETTIMEOUT, ///< Thread-safe Task::setTimeout()
- TASK_REQUEST_RESETTIMEOUT, ///< Thread-safe Task::resetTimeout()
- #endif // _TASK_TIMEOUT
- #ifdef _TASK_STATUS_REQUEST
- TASK_REQUEST_WAITFOR, ///< Thread-safe Task::waitFor()
- TASK_REQUEST_WAITFORDELAYED, ///< Thread-safe Task::waitForDelayed()
- #endif // _TASK_STATUS_REQUEST
- #ifdef _TASK_WDT_IDS
- TASK_REQUEST_SETID, ///< Thread-safe Task::setId()
- TASK_REQUEST_SETCONTROLPOINT, ///< Thread-safe Task::setControlPoint()
- #endif // _TASK_WDT_IDS
- TASK_REQUEST_ENABLE, ///< Thread-safe Task::enable()
- TASK_REQUEST_ENABLEIFNOT, ///< Thread-safe Task::enableIfNot()
- TASK_REQUEST_ENABLEDELAYED, ///< Thread-safe Task::enableDelayed()
- TASK_REQUEST_RESTART, ///< Thread-safe Task::restart()
- TASK_REQUEST_RESTARTDELAYED, ///< Thread-safe Task::restartDelayed()
- TASK_REQUEST_DELAY, ///< Thread-safe Task::delay()
- TASK_REQUEST_ADJUST, ///< Thread-safe Task::adjust()
- TASK_REQUEST_FORCENEXTITERATION, ///< Thread-safe Task::forceNextIteration()
- TASK_REQUEST_DISABLE, ///< Thread-safe Task::disable()
- TASK_REQUEST_ABORT, ///< Thread-safe Task::abort()
- TASK_REQUEST_CANCEL, ///< Thread-safe Task::cancel()
- TASK_REQUEST_SET, ///< Thread-safe Task::set()
- TASK_REQUEST_SETINTERVAL, ///< Thread-safe Task::setInterval()
- TASK_REQUEST_SETINTERVALNODELAY, ///< Thread-safe Task::setIntervalNodelay()
- TASK_REQUEST_SETITERATIONS, ///< Thread-safe Task::setIterations()
- TASK_REQUEST_SETCALLBACK, ///< Thread-safe Task::setCallback()
- TASK_REQUEST_SETONENABLE, ///< Thread-safe Task::setOnEnable()
- TASK_REQUEST_SETONDISABLE ///< Thread-safe Task::setOnDisable()
- } _task_request_type_t;
- #ifdef _TASK_STATUS_REQUEST
- // void setWaiting(unsigned int aCount = 1);
- #define TASK_SR_REQUEST_SETWAITING_1 TASK_SR_REQUEST_SETWAITING
- #define TASK_SR_REQUEST_SETWAITING_1_DEFAULT 1
- // __TASK_IRAM signal(int aStatus = 0);
- #define TASK_SR_REQUEST_SIGNAL_1 TASK_SR_REQUEST_SIGNAL
- #define TASK_SR_REQUEST_SIGNAL_1_DEFAULT 0
- // __TASK_IRAM signalComplete(int aStatus = 0);
- #define TASK_SR_REQUEST_SIGNALCOMPLETE_1 TASK_SR_REQUEST_SIGNALCOMPLETE
- #define TASK_SR_REQUEST_SIGNALCOMPLETE_1_DEFAULT 0
- #ifdef _TASK_TIMEOUT
- // void setTimeout(unsigned long aTimeout)
- #define TASK_SR_REQUEST_SETTIMEOUT_1 TASK_SR_REQUEST_SETTIMEOUT
- // void resetTimeout();
- #define TASK_SR_REQUEST_RESETTIMEOUT_0 TASK_SR_REQUEST_RESETTIMEOUT
- #endif // _TASK_TIMEOUT
- #endif
- #ifdef _TASK_LTS_POINTER
- // void setLtsPointer(void *aPtr);
- #define TASK_REQUEST_SETLTSPOINTER_1 TASK_REQUEST_SETLTSPOINTER
- #endif
- #ifdef _TASK_SELF_DESTRUCT
- // void setSelfDestruct(bool aSelfDestruct=true)
- #define TASK_REQUEST_SETSELFDESTRUCT_1 TASK_REQUEST_SETSELFDESTRUCT
- #define TASK_REQUEST_SETSELFDESTRUCT_1_DEFAULT true
- #endif
- #ifdef _TASK_SCHEDULING_OPTIONS
- // void setSchedulingOption(unsigned int aOption)
- #define TASK_REQUEST_SETSCHEDULINGOPTION_1 TASK_REQUEST_SETSCHEDULINGOPTION
- #endif
- #ifdef _TASK_TIMEOUT
- // void setTimeout(unsigned long aTimeout, bool aReset=false);
- #define TASK_REQUEST_SETTIMEOUT_2 TASK_REQUEST_SETTIMEOUT
- #define TASK_REQUEST_SETTIMEOUT_2_DEFAULT false
- // void resetTimeout();
- #define TASK_REQUEST_RESETTIMEOUT_0 TASK_REQUEST_RESETTIMEOUT
- #endif // _TASK_TIMEOUT
- #ifdef _TASK_STATUS_REQUEST
- // bool waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
- #define TASK_REQUEST_WAITFOR_3 TASK_REQUEST_WAITFOR
- #define TASK_REQUEST_WAITFOR_2_DEFAULT 0
- #define TASK_REQUEST_WAITFOR_3_DEFAULT 1
- // bool waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
- #define TASK_REQUEST_WAITFORDELAYED_3 TASK_REQUEST_WAITFORDELAYED
- #define TASK_REQUEST_WAITFORDELAYED_2_DEFAULT 0
- #define TASK_REQUEST_WAITFORDELAYED_3_DEFAULT 1
- #endif // _TASK_STATUS_REQUEST
- #ifdef _TASK_WDT_IDS
- // __TASK_INLINE void setId(unsigned int aID) ;
- #define TASK_REQUEST_SETID_1 TASK_REQUEST_SETID
- // __TASK_INLINE void setControlPoint(unsigned int aPoint) ;
- #define TASK_REQUEST_SETCONTROLPOINT_1 TASK_REQUEST_SETCONTROLPOINT
- #endif // _TASK_WDT_IDS
- // bool __TASK_IRAM enable();
- #define TASK_REQUEST_ENABLE_0 TASK_REQUEST_ENABLE
- // bool __TASK_IRAM enableIfNot();
- #define TASK_REQUEST_ENABLEIFNOT_0 TASK_REQUEST_ENABLEIFNOT
- // bool __TASK_IRAM enableDelayed(unsigned long aDelay=0);
- #define TASK_REQUEST_ENABLEDELAYED_1 TASK_REQUEST_ENABLEDELAYED
- #define TASK_REQUEST_ENABLEDELAYED_1_DEFAULT 0
- // bool __TASK_IRAM restart();
- #define TASK_REQUEST_RESTART_0 TASK_REQUEST_RESTART
- // bool __TASK_IRAM restartDelayed(unsigned long aDelay=0);
- #define TASK_REQUEST_RESTARTDELAYED_1 TASK_REQUEST_RESTARTDELAYED
- #define TASK_REQUEST_RESTARTDELAYED_1_DEFAULT 0
- // void __TASK_IRAM delay(unsigned long aDelay=0);
- #define TASK_REQUEST_DELAY_1 TASK_REQUEST_DELAY
- #define TASK_REQUEST_DELAY_1_DEFAULT 0
- // void adjust(long aInterval);
- #define TASK_REQUEST_ADJUST_1 TASK_REQUEST_ADJUST
- // void __TASK_IRAM forceNextIteration();
- #define TASK_REQUEST_FORCENEXTITERATION_0 TASK_REQUEST_FORCENEXTITERATION
- // bool disable();
- #define TASK_REQUEST_DISABLE_0 TASK_REQUEST_DISABLE
- // void abort();
- #define TASK_REQUEST_ABORT_0 TASK_REQUEST_ABORT
- // void cancel();
- #define TASK_REQUEST_CANCEL_0 TASK_REQUEST_CANCEL
- // void set(unsigned long aInterval, long aIterations, TaskCallback aCallback,TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
- #define TASK_REQUEST_SET_5 TASK_REQUEST_SET
- #define TASK_REQUEST_SET_4_DEFAULT NULL
- #define TASK_REQUEST_SET_5_DEFAULT NULL
- // void setInterval(unsigned long aInterval);
- #define TASK_REQUEST_SETINTERVAL_1 TASK_REQUEST_SETINTERVAL
- // void setIntervalNodelay(unsigned long aInterval, unsigned int aOption = TASK_INTERVAL_KEEP);
- #define TASK_REQUEST_SETINTERVALNODELAY_2 TASK_REQUEST_SETINTERVALNODELAY
- #define TASK_REQUEST_SETINTERVALNODELAY_2_DEFAULT TASK_INTERVAL_KEEP
- // void setIterations(long aIterations);
- #define TASK_REQUEST_SETITERATIONS_1 TASK_REQUEST_SETITERATIONS
- // void setCallback(TaskCallback aCallback)
- #define TASK_REQUEST_SETCALLBACK_1 TASK_REQUEST_SETCALLBACK
- // setOnEnable(TaskOnEnable aCallback) ;
- #define TASK_REQUEST_SETONENABLE_1 TASK_REQUEST_SETONENABLE
- // setOnDisable(TaskOnDisable aCallback) ;
- #define TASK_REQUEST_SETONDISABLE_1 TASK_REQUEST_SETONDISABLE
- /**
- * @struct _task_request_t
- * @brief Structure for thread-safe task operation requests
- *
- * @details This structure is used to call Scheduler::requestAction() and provide parameters
- * to the respective API method in a thread-safe manner. When _TASK_THREAD_SAFE is enabled,
- * this structure allows tasks to be controlled safely from interrupt contexts or other threads
- * by queuing requests that are processed atomically during the scheduler's execute() cycle.
- *
- * The structure contains the request type and up to 5 parameters that correspond to the
- * parameters of the target Task or StatusRequest method being called. The scheduler will
- * unpack these parameters and call the appropriate method during its execution.
- *
- * Usage example:
- * @code
- * _task_request_t request;
- * request.req_type = TASK_REQUEST_ENABLE;
- * request.object_ptr = &myTask;
- * // param1-param5 not needed for enable()
- * scheduler.requestAction(&request);
- * @endcode
- *
- * @note Only available when compiled with _TASK_THREAD_SAFE support.
- *
- * @see Scheduler::requestAction(), _task_request_type_t
- */
- typedef struct {
- _task_request_type_t req_type; ///< Type of request (corresponds to Task/StatusRequest method)
- void* object_ptr; ///< Pointer to Task or StatusRequest object to operate on
- unsigned long param1; ///< First parameter for the target method (if needed)
- unsigned long param2; ///< Second parameter for the target method (if needed)
- unsigned long param3; ///< Third parameter for the target method (if needed)
- unsigned long param4; ///< Fourth parameter for the target method (if needed)
- unsigned long param5; ///< Fifth parameter for the target method (if needed)
- } _task_request_t;
- #endif //_TASK_THREAD_SAFE
- #ifdef _TASK_STATUS_REQUEST
- /**
- * @defgroup StatusRequestCodes Status Request Return Codes
- * @brief Status codes returned by StatusRequest operations
- * @{
- */
- /**
- * @def TASK_SR_OK
- * @brief Successful completion status
- * @details Default successful completion status for StatusRequest operations.
- */
- #define TASK_SR_OK 0
- /**
- * @def TASK_SR_ERROR
- * @brief General error status
- * @details Indicates an error condition occurred during StatusRequest operation.
- */
- #define TASK_SR_ERROR (-1)
- /**
- * @def TASK_SR_CANCEL
- * @brief Cancelled status
- * @details Indicates the StatusRequest operation was cancelled.
- */
- #define TASK_SR_CANCEL (-32766)
- /**
- * @def TASK_SR_ABORT
- * @brief Aborted status
- * @details Indicates the StatusRequest operation was aborted.
- */
- #define TASK_SR_ABORT (-32767)
- /**
- * @def TASK_SR_TIMEOUT
- * @brief Timeout status
- * @details Indicates the StatusRequest operation timed out.
- */
- #define TASK_SR_TIMEOUT (-32768)
- /** @} */ // End of StatusRequestCodes group
- /**
- * @defgroup StatusRequestModes Status Request Internal Modes
- * @brief Internal mode constants for StatusRequest operations
- * @{
- */
- /**
- * @def _TASK_SR_NODELAY
- * @brief No delay mode for StatusRequest
- */
- #define _TASK_SR_NODELAY 1
- /**
- * @def _TASK_SR_DELAY
- * @brief Delay mode for StatusRequest
- */
- #define _TASK_SR_DELAY 2
- /** @} */ // End of StatusRequestModes group
- /**
- * @class StatusRequest
- * @brief Status Request object for event-driven task invocation
- *
- * @details StatusRequest objects allow tasks to wait on an event and signal event completion to each other.
- * This enables event-driven programming where one task can "signal" completion of its function via a
- * StatusRequest object, and other tasks can "wait" on the same StatusRequest object.
- *
- * Key features:
- * - Can wait for multiple events (set via setWaiting())
- * - Supports timeout functionality
- * - Provides completion status codes
- * - Thread-safe signaling mechanisms
- *
- * @note Each task has an internal StatusRequest object that is:
- * - Always waits on 1 event (completion of this task)
- * - Activated (set to "waiting" status) after Task is enabled
- * - Completed after Task is disabled
- *
- * @see Task::waitFor(), Task::waitForDelayed()
- */
- class StatusRequest {
- friend class Scheduler;
- public:
- /**
- * @brief Default constructor
- * @details Creates Status Request object with "completed" status on creation.
- */
- __TASK_INLINE StatusRequest();
- /**
- * @brief Activates Status Request object
- * @param aCount Number of events to wait for (default = 1)
- * @details By default each object waits on one event only. If aCount is supplied,
- * StatusRequest can wait on multiple events. For example, setWaiting(3) will wait
- * on three signals - useful for waiting for completion of measurements from 3 sensors.
- */
- __TASK_INLINE void setWaiting(unsigned int aCount = 1);
- /**
- * @brief Signals completion of one event
- * @param aStatus Completion code (default = 0)
- * @return true if signal was processed successfully
- * @details Signals completion of the event to the StatusRequest object and passes
- * a completion code. Passing a negative status code is considered reporting an error
- * condition and will complete the status request regardless of how many outstanding
- * signals it is still waiting for. Only the latest status code is kept.
- */
- __TASK_INLINE bool signal(int aStatus = 0);
- /**
- * @brief Signals completion of ALL events
- * @param aStatus Completion code (default = 0)
- * @details Signals completion of ALL events to the StatusRequest object and passes
- * a completion code. The status request completes regardless of how many events
- * it is still waiting on.
- */
- __TASK_INLINE void signalComplete(int aStatus = 0);
- /**
- * @brief Check if status request is pending (deprecated)
- * @return true if status request is still waiting for events
- * @deprecated Use isPending() instead
- */
- __TASK_INLINE bool pending() { return isPending(); };
- /**
- * @brief Check if status request is pending
- * @return true if status request is still waiting for events to happen
- */
- __TASK_INLINE bool isPending();
- /**
- * @brief Check if status request is completed (deprecated)
- * @return true if status request event has completed
- * @deprecated Use isCompleted() instead
- */
- __TASK_INLINE bool completed() { return isCompleted(); };
- /**
- * @brief Check if status request is completed
- * @return true if status request event has completed
- */
- __TASK_INLINE bool isCompleted();
- /**
- * @brief Get the status code
- * @return The status code passed to signal() and signalComplete() methods
- * @details Any positive number is considered successful completion status.
- * A 0 (zero) is considered default successful completion status.
- * Any negative number is considered an error code and unsuccessful completion.
- */
- __TASK_INLINE int getStatus();
- /**
- * @brief Get count of remaining events
- * @return The count of events not yet completed
- * @details Typically by default a StatusRequest object only waits on 1 event.
- * However, when waiting on multiple events, returns number of events not yet completed.
- */
- __TASK_INLINE int getCount();
-
- #ifdef _TASK_TIMEOUT
- /**
- * @brief Set timeout for this StatusRequest object
- * @param aTimeout Timeout interval in milliseconds (or microseconds)
- * @details When enabled, the activated StatusRequest object will complete with
- * the code TASK_SR_TIMEOUT if no other process calls its signal() or signalComplete() method.
- */
- __TASK_INLINE void setTimeout(unsigned long aTimeout) { iTimeout = aTimeout; };
- /**
- * @brief Get timeout interval
- * @return The timeout interval for the current StatusRequest object
- * @details This is the full original interval, not the remaining time.
- */
- __TASK_INLINE unsigned long getTimeout() { return iTimeout; };
- /**
- * @brief Reset timeout counter
- * @details Resets the current timeout counter to the original value.
- * The timeout countdown starts from the beginning again.
- */
- __TASK_INLINE void resetTimeout();
- /**
- * @brief Get time until timeout
- * @return Number of milliseconds (or microseconds) until timeout
- * @details The value could be negative if the timeout has already occurred.
- */
- __TASK_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 (see TASK_SR_ constants)
- #ifdef _TASK_TIMEOUT
- unsigned long iTimeout; // Task overall timeout
- unsigned long iStarttime; // millis at task start time
- #endif // _TASK_TIMEOUT
- };
- #endif // _TASK_STATUS_REQUEST
- /**
- * @defgroup CallbackTypes Task Callback Types
- * @brief Type definitions for task callback functions
- * @{
- */
- #ifdef _TASK_STD_FUNCTION
- #include <functional>
- /**
- * @typedef TaskCallback
- * @brief Main task callback function type (std::function version)
- * @details Function called periodically when task is executed. Should be non-blocking
- * and return quickly to maintain cooperative multitasking behavior.
- */
- typedef std::function<void()> TaskCallback;
- /**
- * @typedef TaskOnDisable
- * @brief Task disable callback function type (std::function version)
- * @details Function called when task is disabled. Used for cleanup operations.
- */
- typedef std::function<void()> TaskOnDisable;
- /**
- * @typedef TaskOnEnable
- * @brief Task enable callback function type (std::function version)
- * @details Function called when task is enabled. Should return true to enable task,
- * false to keep task disabled. Used for initialization operations.
- */
- typedef std::function<bool()> TaskOnEnable;
- #else
- /**
- * @typedef TaskCallback
- * @brief Main task callback function pointer type
- * @details Function called periodically when task is executed. Should be non-blocking
- * and return quickly to maintain cooperative multitasking behavior.
- */
- typedef void (*TaskCallback)();
- /**
- * @typedef TaskOnDisable
- * @brief Task disable callback function pointer type
- * @details Function called when task is disabled. Used for cleanup operations.
- */
- typedef void (*TaskOnDisable)();
- /**
- * @typedef TaskOnEnable
- * @brief Task enable callback function pointer type
- * @details Function called when task is enabled. Should return true to enable task,
- * false to keep task disabled. Used for initialization operations.
- */
- typedef bool (*TaskOnEnable)();
- #endif // _TASK_STD_FUNCTION
- /** @} */ // End of CallbackTypes group
- #ifdef _TASK_SLEEP_ON_IDLE_RUN
- /**
- * @typedef SleepCallback
- * @brief Sleep function callback type
- * @param aDuration Duration to sleep in milliseconds
- * @details Function pointer type for custom sleep implementations during idle periods.
- */
- typedef void (*SleepCallback)( unsigned long aDuration );
- /**
- * @brief Global pointer to scheduler that controls sleep functionality
- */
- extern Scheduler* iSleepScheduler;
- /**
- * @brief Global pointer to custom sleep method
- */
- extern SleepCallback iSleepMethod;
- #endif // _TASK_SLEEP_ON_IDLE_RUN
- /**
- * @struct _task_status
- * @brief Internal task status structure
- * @details Bit-packed structure containing task state flags for efficient memory usage.
- * This structure tracks various task states and conditions.
- */
- 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 task has been canceled prior to normal end of all iterations or regular call to disable()
- #ifdef _TASK_SELF_DESTRUCT
- bool selfdestruct : 1; ///< Indication that task has been requested to self-destruct on disable
- bool sd_request : 1; ///< Request for scheduler to delete task object and take task out of the queue
- #endif // _TASK_SELF_DESTRUCT
- #ifdef _TASK_STATUS_REQUEST
- uint8_t waiting : 2; ///< Indication if task is waiting on the status request
- #endif // _TASK_STATUS_REQUEST
- #ifdef _TASK_TIMEOUT
- bool timeout : 1; ///< Indication if task timed out
- #endif // _TASK_TIMEOUT
- } _task_status;
- /**
- * @class Task
- * @brief Core task class for cooperative multitasking
- *
- * @details A "Task" is an action, a part of the program logic, which requires scheduled execution.
- * A concept of Task combines the following aspects:
- * - Program code performing specific activities (callback methods)
- * - Execution interval
- * - Number of execution iterations
- * - (Optionally) Execution start event (Status Request)
- * - (Optionally) Pointer to a Local Task Storage area
- *
- * Tasks perform certain functions, which could require periodic or one-time execution,
- * update of specific variables, or waiting for specific events. Tasks also could be
- * controlling specific hardware, or triggered by hardware interrupts.
- *
- * For execution purposes Tasks are linked into execution chains, which are processed
- * by the Scheduler in the order they were added (linked together).
- *
- * Key Features:
- * - Cooperative multitasking (non-preemptive)
- * - Event-driven execution via StatusRequest objects
- * - Dynamic parameter adjustment during runtime
- * - Support for callback chaining and state machines
- * - Built-in timeout and watchdog functionality
- * - Local task storage for task-specific data
- *
- * @note Tasks are responsible for supporting cooperative multitasking by being "good neighbors",
- * i.e., running their callback methods quickly in a non-blocking way, and releasing control
- * back to the scheduler as soon as possible.
- *
- * @see Scheduler, StatusRequest
- */
- class Task {
- friend class Scheduler;
- public:
- /**
- * @brief Task constructor with parameters
- * @param aInterval Execution interval in milliseconds (or microseconds if _TASK_MICRO_RES enabled) (default = 0)
- * @param aIterations Number of iterations, -1 for indefinite execution (default = 0)
- * @param aScheduler Optional reference to existing scheduler. If supplied (not NULL) this task will be appended to the task chain (default = NULL)
- * @param aEnable Optional. Value of true will create task enabled (default = false)
- *
- * @details Creates a task that is scheduled to run every aInterval milliseconds, aIterations times.
- * All tasks are created disabled by default (unless aEnable = true). You have to explicitly enable
- * the task for execution.
- *
- * @note Tasks do not remember the number of iterations set initially. After the iterations are done,
- * internal iteration counter is 0. If you need to perform another set of iterations, you need to set
- * the number of iterations again.
- *
- * @note Tasks which performed all their iterations remain active.
- */
- #ifdef _TASK_OO_CALLBACKS
- __TASK_INLINE Task(unsigned long aInterval=0, long aIterations=0, Scheduler* aScheduler=NULL, bool aEnable=false
- #ifdef _TASK_SELF_DESTRUCT
- , bool aSelfDestruct=false);
- #else
- );
- #endif // #ifdef _TASK_SELF_DESTRUCT
- #else
- /**
- * @brief Task constructor with callback parameters
- * @param aInterval Execution interval in milliseconds (or microseconds if _TASK_MICRO_RES enabled) (default = 0)
- * @param aIterations Number of iterations, -1 for indefinite execution (default = 0)
- * @param aCallback Pointer to the void callback method without parameters (default = NULL)
- * @param aScheduler Optional reference to existing scheduler. If supplied (not NULL) this task will be appended to the task chain (default = NULL)
- * @param aEnable Optional. Value of true will create task enabled (default = false)
- * @param aOnEnable Pointer to the bool OnEnable callback method without parameters, invoked when task is enabled (default = NULL)
- * @param aOnDisable Pointer to the void OnDisable method without parameters, invoked when task is disabled (default = NULL)
- *
- * @details Creates a task with callback methods. OnEnable method returns true if task should be enabled,
- * false if it should remain disabled. OnDisable method is called when task is disabled.
- *
- * @note OnEnable callback method is called immediately when task is enabled, which could be well ahead
- * of the scheduled execution time of the task. It is advisable to explicitly enable tasks with OnEnable
- * methods after all initialization methods completed (e.g., at the end of setup() method).
- */
- __TASK_INLINE Task(unsigned long aInterval=0, long aIterations=0, TaskCallback aCallback=NULL, Scheduler* aScheduler=NULL, bool aEnable=false, TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL
- #ifdef _TASK_SELF_DESTRUCT
- , bool aSelfDestruct=false);
- #else
- );
- #endif // #ifdef _TASK_SELF_DESTRUCT
- #endif // _TASK_OO_CALLBACKS
- #ifdef _TASK_STATUS_REQUEST
- #ifdef _TASK_OO_CALLBACKS
- /**
- * @brief Constructor for StatusRequest-based tasks (Object-Oriented callbacks)
- * @param aScheduler Pointer to scheduler
- * @details Creates a Task for activation on event. Such tasks must run waitFor() method,
- * their interval, iteration and enabled status will be set by that method.
- */
- __TASK_INLINE Task(Scheduler* aScheduler);
- #else
- /**
- * @brief Constructor for StatusRequest-based tasks (Function pointer callbacks)
- * @param aCallback Pointer to callback function
- * @param aScheduler Pointer to scheduler
- * @param aOnEnable Pointer to OnEnable callback (default = NULL)
- * @param aOnDisable Pointer to OnDisable callback (default = NULL)
- * @details Creates a Task for activation on event. Such tasks must run waitFor() method,
- * their interval, iteration and enabled status will be set by that method.
- */
- __TASK_INLINE Task(TaskCallback aCallback, Scheduler* aScheduler, TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
- #endif // _TASK_OO_CALLBACKS
- #endif // _TASK_STATUS_REQUEST
- /**
- * @brief Virtual destructor
- * @details Properly destroys the task object and cleans up resources.
- */
- virtual __TASK_INLINE ~Task();
- #ifdef _TASK_TIMEOUT
- /**
- * @brief Set overall task timeout
- * @param aTimeout Timeout period in milliseconds (or microseconds)
- * @param aReset Whether to reset timeout counter (default = false)
- * @details Any task can be set to time out after a certain period of time.
- * Timeout can be reset, so it can be used as an individual Task's watchdog timer.
- */
- __TASK_INLINE void setTimeout(unsigned long aTimeout, bool aReset=false);
- /**
- * @brief Reset timeout counter
- * @details Resets the timeout counter to start counting from the beginning.
- */
- __TASK_INLINE void resetTimeout();
- /**
- * @brief Get timeout value
- * @return Current timeout value in milliseconds (or microseconds)
- */
- __TASK_INLINE unsigned long getTimeout();
- /**
- * @brief Get time until timeout
- * @return Number of milliseconds (or microseconds) until timeout occurs
- * @details Returns negative value if timeout has already occurred.
- */
- __TASK_INLINE long untilTimeout();
- /**
- * @brief Check if task has timed out (deprecated)
- * @return true if task has timed out
- * @deprecated Use isTimedOut() instead
- */
- __TASK_INLINE bool timedOut() { return isTimedOut(); };
- /**
- * @brief Check if task has timed out
- * @return true if task has timed out
- */
- __TASK_INLINE bool isTimedOut();
- #endif
- /**
- * @brief Enable the task
- * @return true if task was successfully enabled
- * @details Enables the task and schedules it for immediate execution (without delay) at this or next
- * scheduling pass. Scheduler will execute the next pass without any delay because there is a task
- * which was enabled and requires execution.
- *
- * @note If task being enabled is not assigned to a scheduler and is not part of execution chain,
- * then task will not be enabled.
- *
- * @note enable() invokes task's OnEnable method (if not NULL) immediately, which can prepare task
- * for execution. OnEnable must return true for task to be enabled. If OnEnable returns false,
- * task remains disabled.
- *
- * @warning OnEnable is invoked every time enable() is called, regardless if task is already enabled.
- * Alignment to current millis() is performed after OnEnable exits.
- */
- __TASK_INLINE bool enable();
- /**
- * @brief Enable the task only if it was previously disabled
- * @return Previous enable state: true if task was already enabled, false if task was disabled
- * @details Since enable() schedules Task for execution immediately, this method provides a way
- * to activate tasks and schedule them for immediate execution only if they are not active already.
- * All NOTES from the enable() method apply.
- */
- __TASK_INLINE bool enableIfNot();
- /**
- * @brief Enable the task with delay
- * @param aDelay Delay before first execution in milliseconds (default = 0)
- * @return true if task was successfully enabled
- * @details Enables the task and schedules it for execution after a specific delay.
- */
- __TASK_INLINE bool enableDelayed(unsigned long aDelay=0);
- /**
- * @brief Restart the task
- * @return true if task was successfully restarted
- * @details For tasks with limited number of iterations only, restart method will re-enable the task,
- * set the number of iterations back to last set value, and schedule task for execution as soon as possible.
- */
- __TASK_INLINE bool restart();
- /**
- * @brief Restart the task with delay
- * @param aDelay Delay before first execution in milliseconds (default = 0)
- * @return true if task was successfully restarted
- * @details Same as restart() method, with the only difference being that Task is scheduled to run
- * first iteration after a delay.
- */
- __TASK_INLINE bool restartDelayed(unsigned long aDelay=0);
- /**
- * @brief Delay the task execution
- * @param aDelay Delay in milliseconds (default = 0)
- * @details Schedules the task for execution after a delay, but does not change the enabled/disabled
- * status of the task. A delay of 0 (zero) will delay task for current execution interval.
- * Use forceNextIteration() method to force execution during immediate next scheduling pass.
- */
- __TASK_INLINE void delay(unsigned long aDelay=0);
- /**
- * @brief Adjust task interval
- * @param aInterval New interval value (can be negative for adjustment)
- * @details Adjusts the task execution interval by the specified amount.
- */
- __TASK_INLINE void adjust(long aInterval);
- /**
- * @brief Force next iteration to execute immediately
- * @details Schedules the task for execution during immediate next scheduling pass.
- * The Task must be already enabled prior to this method. Task's schedule is adjusted
- * to run from this moment in time.
- *
- * @note If a task was running every 10 seconds: 10, 20, 30, calling forceNextIteration
- * at 44th second will make subsequent schedule look like: 44, 54, 64, 74, ..
- */
- __TASK_INLINE void forceNextIteration();
- /**
- * @brief Disable the task
- * @return Previous enabled state: true if task was enabled, false otherwise
- * @details Scheduler will not execute this task any longer, even if it remains in the chain.
- * Task can be later re-enabled for execution. If not NULL, task's OnDisable method is invoked
- * almost immediately (actually during the next scheduling pass).
- * OnDisable is invoked only if task was in enabled state.
- */
- __TASK_INLINE bool disable();
- /**
- * @brief Abort the task
- * @details Immediately stops task execution and marks it as aborted.
- * Different from disable() in that it indicates abnormal termination.
- * OnDisable method is NOT invoked for Aborted tasks.
- */
- __TASK_INLINE void abort();
- /**
- * @brief Cancel the task
- * @details Marks the task as cancelled, indicating it was stopped before normal completion.
- * OnDisable method is invoked if task was in enabled state.
- */
- __TASK_INLINE void cancel();
- /**
- * @brief Check if task is enabled
- * @return true if task is enabled
- */
- __TASK_INLINE bool isEnabled();
- /**
- * @brief Check if task is cancelled
- * @return true if task has been cancelled
- */
- __TASK_INLINE bool isCanceled();
- /**
- * @brief Check if task is cancelled (deprecated)
- * @return true if task has been cancelled
- * @deprecated Use isCanceled() instead
- */
- __TASK_INLINE bool canceled() { return isCanceled(); };
- #ifdef _TASK_SCHEDULING_OPTIONS
- /**
- * @brief Get the current scheduling option for this task
- *
- * Returns the current scheduling behavior option that determines how the task's
- * interval and iterations are managed during execution.
- *
- * Available scheduling options:
- * - TASK_SCHEDULE: Default behavior - interval countdown starts after OnEnable
- * - TASK_SCHEDULE_NC: No countdown - interval countdown starts immediately upon enable
- * - TASK_INTERVAL: Interval mode - maintains exact intervals regardless of execution time
- *
- * @return unsigned int Current scheduling option value (TASK_SCHEDULE, TASK_SCHEDULE_NC, or TASK_INTERVAL)
- *
- * @note This method is only available when _TASK_SCHEDULING_OPTIONS compile-time option is enabled
- * @see setSchedulingOption(), TASK_SCHEDULE, TASK_SCHEDULE_NC, TASK_INTERVAL
- * @since Version 3.0.0
- */
- __TASK_INLINE unsigned int getSchedulingOption() { return iOption; }
- /**
- * @brief Set the scheduling option for this task
- *
- * Sets the scheduling behavior option that determines how the task's interval
- * and iterations are managed during execution. This affects when the interval
- * countdown begins and how timing is calculated.
- *
- * Scheduling options:
- * - TASK_SCHEDULE: (Default) Interval countdown starts after OnEnable callback completes
- * - TASK_SCHEDULE_NC: No countdown - interval countdown starts immediately when task is enabled
- * - TASK_INTERVAL: Interval mode - maintains exact intervals by accounting for execution time
- *
- * @param aOption The scheduling option to set (TASK_SCHEDULE, TASK_SCHEDULE_NC, or TASK_INTERVAL)
- *
- * @note This method is only available when _TASK_SCHEDULING_OPTIONS compile-time option is enabled
- * @note The scheduling option can be changed at any time, even when the task is running
- * @warning Using TASK_INTERVAL may cause timing drift if task execution time exceeds the interval
- * @see getSchedulingOption(), TASK_SCHEDULE, TASK_SCHEDULE_NC, TASK_INTERVAL
- * @since Version 3.0.0
- */
- __TASK_INLINE void setSchedulingOption(unsigned int aOption) { iOption = aOption; }
- #endif //_TASK_SCHEDULING_OPTIONS
- #ifdef _TASK_OO_CALLBACKS
- /**
- * @brief Set task parameters (Object-Oriented callbacks)
- * @param aInterval Execution interval in milliseconds (or microseconds)
- * @param aIterations Number of iterations (-1 for infinite)
- * @details Allows dynamic control of task execution parameters in one method call.
- */
- __TASK_INLINE void set(unsigned long aInterval, long aIterations);
- #else
- /**
- * @brief Set task parameters (Function pointer callbacks)
- * @param aInterval Execution interval in milliseconds (or microseconds)
- * @param aIterations Number of iterations (-1 for infinite)
- * @param aCallback Pointer to callback function
- * @param aOnEnable Pointer to OnEnable callback (default = NULL)
- * @param aOnDisable Pointer to OnDisable callback (default = NULL)
- * @details Allows dynamic control of task execution parameters in one method call.
- * OnEnable and OnDisable parameters can be omitted (assigned to NULL).
- */
- __TASK_INLINE void set(unsigned long aInterval, long aIterations, TaskCallback aCallback,TaskOnEnable aOnEnable=NULL, TaskOnDisable aOnDisable=NULL);
- #endif // _TASK_OO_CALLBACKS
- /**
- * @brief Set task execution interval
- * @param aInterval New interval in milliseconds (or microseconds)
- * @details Next execution time calculation takes place after the callback method is called,
- * so new interval will be used immediately by the scheduler. Execution is delayed by the
- * provided interval. If immediate invocation is required, call forceNextIteration() after
- * setting new interval or use setIntervalNoDelay() method.
- */
- __TASK_INLINE void setInterval(unsigned long aInterval);
- /**
- * @brief Set task interval without delay
- * @param aInterval New interval in milliseconds (or microseconds)
- * @param aOption How to handle the interval change (default = TASK_INTERVAL_KEEP)
- * TASK_INTERVAL_KEEP - keep the current delay, new interval will be used after current delay expires
- * TASK_INTERVAL_RECALC - recalculate next execution time based on new interval
- * TASK_INTERVAL_RESET - reset schedule, next execution time and new interval are updated
- * @details Sets new interval and provides options for how to handle the timing change.
- */
- __TASK_INLINE void setIntervalNodelay(unsigned long aInterval, unsigned int aOption = TASK_INTERVAL_KEEP);
- /**
- * @brief Get current task interval
- * @return Current execution interval in milliseconds (or microseconds)
- */
- __TASK_INLINE unsigned long getInterval();
- /**
- * @brief Set number of iterations
- * @param aIterations Number of iterations (-1 for infinite)
- * @details Tasks that ran through all their allocated iterations are disabled.
- * SetIterations() method DOES NOT enable the task. Either enable explicitly,
- * or use restart methods.
- */
- __TASK_INLINE void setIterations(long aIterations);
- /**
- * @brief Get remaining iterations
- * @return Number of remaining iterations
- */
- __TASK_INLINE long getIterations();
- /**
- * @brief Get run counter
- * @return Number of times callback method has been invoked since last enable
- * @details The runCounter value is incremented before callback method is invoked.
- * If a task is checking the runCounter value within its callback method, then
- * the first run value is 1.
- */
- __TASK_INLINE unsigned long getRunCounter();
-
- #ifdef _TASK_SELF_DESTRUCT
- /**
- * @brief Enable or disable self-destruction for this task
- *
- * When self-destruction is enabled, the task will automatically delete itself
- * from the scheduler after it completes its final iteration. This is useful
- * for one-time or temporary tasks that should clean themselves up automatically.
- *
- * Self-destruction behavior:
- * - Task removes itself from the scheduler when it finishes its last iteration
- * - Applies to tasks with finite iterations (setIterations() > 0)
- * - Does not apply to infinite tasks (TASK_FOREVER iterations)
- * - Task object memory is not freed - only removed from scheduler
- *
- * @param aSelfDestruct True to enable self-destruction, false to disable (default: true)
- *
- * @note This method is only available when _TASK_SELF_DESTRUCT compile-time option is enabled
- * @note Self-destruction only occurs after the task naturally completes its iterations
- * @note Manually disabled tasks will not self-destruct
- * @warning Ensure task object remains valid until self-destruction occurs
- * @see getSelfDestruct(), setIterations(), disable()
- * @since Version 3.0.0
- */
- __TASK_INLINE void setSelfDestruct(bool aSelfDestruct=true) { iStatus.selfdestruct = aSelfDestruct; }
- /**
- * @brief Check if self-destruction is enabled for this task
- *
- * Returns whether the task is configured to automatically remove itself from
- * the scheduler after completing its final iteration.
- *
- * @return bool True if self-destruction is enabled, false otherwise
- *
- * @note This method is only available when _TASK_SELF_DESTRUCT compile-time option is enabled
- * @see setSelfDestruct(), setIterations()
- * @since Version 3.0.0
- */
- __TASK_INLINE bool getSelfDestruct() { return iStatus.selfdestruct; }
- #endif // #ifdef _TASK_SELF_DESTRUCT
- #ifdef _TASK_OO_CALLBACKS
- /**
- * @brief Pure virtual main task execution callback (Object-Oriented mode)
- *
- * This pure virtual method must be implemented by derived classes to define
- * the task's main execution logic. Called by the scheduler when the task
- * is ready to execute based on its timing and iteration settings.
- *
- * @return bool True if the execution was "productive" (performed meaningful work),
- * false if the task was idle. A productive return value prevents
- * the scheduler from entering sleep mode on the next idle cycle,
- * optimizing power management for active tasks.
- *
- * @note Only available when _TASK_OO_CALLBACKS compile-time option is enabled
- * @note This is a pure virtual function - derived classes MUST implement it
- * @note Return value affects power management in _TASK_SLEEP_ON_IDLE_RUN mode
- * @see _TASK_OO_CALLBACKS, _TASK_SLEEP_ON_IDLE_RUN
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * class MyTask : public Task {
- * public:
- * bool Callback() override {
- * // Perform task work
- * Serial.println("Task executing");
- * return true; // Productive execution
- * }
- * };
- * @endcode
- */
- virtual __TASK_INLINE bool Callback() =0;
- /**
- * @brief Virtual task enable lifecycle callback (Object-Oriented mode)
- *
- * Called when the task transitions from disabled to enabled state. Allows
- * derived classes to implement custom initialization logic, resource allocation,
- * or conditional enabling based on system state.
- *
- * @return bool True to allow the task to be enabled, false to prevent enabling.
- * Returning false keeps the task disabled despite the enable request.
- *
- * @note Only available when _TASK_OO_CALLBACKS compile-time option is enabled
- * @note Default implementation returns true (allow enabling)
- * @note Called synchronously during enable() operation
- * @note Conditional enabling useful for resource-dependent tasks
- * @see _TASK_OO_CALLBACKS, enable(), OnDisable()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * class ConditionalTask : public Task {
- * public:
- * bool OnEnable() override {
- * if (systemReady()) {
- * initializeResources();
- * return true; // Allow enabling
- * }
- * return false; // Prevent enabling
- * }
- * };
- * @endcode
- */
- virtual __TASK_INLINE bool OnEnable();
- /**
- * @brief Virtual task disable lifecycle callback (Object-Oriented mode)
- *
- * Called when the task transitions from enabled to disabled state. Allows
- * derived classes to implement custom cleanup logic, resource deallocation,
- * or state preservation when the task is deactivated.
- *
- * @note Only available when _TASK_OO_CALLBACKS compile-time option is enabled
- * @note Called synchronously during disable() operation
- * @note Called during automatic disable (iteration completion, errors)
- * @note Default implementation performs no action
- * @see _TASK_OO_CALLBACKS, disable(), OnEnable()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * class ResourceTask : public Task {
- * public:
- * void OnDisable() override {
- * cleanupResources();
- * saveState();
- * Serial.println("Task disabled");
- * }
- * };
- * @endcode
- */
- virtual __TASK_INLINE void OnDisable();
- #else
- /**
- * @brief Set the main task execution callback function
- *
- * Assigns a new callback function that will be executed when the task runs.
- * The callback function defines the task's main execution logic and is called
- * by the scheduler when the task is ready to execute.
- *
- * @param aCallback Function pointer to the new callback function.
- * Must have signature: void callbackFunction()
- *
- * @note Only available when _TASK_OO_CALLBACKS is NOT enabled (function pointer mode)
- * @note Callback can be changed dynamically during task execution
- * @note Setting nullptr callback is allowed but will result in no-op execution
- * @see TaskCallback, yield(), yieldOnce()
- * @since Version 1.0.0
- *
- * @par Example:
- * @code
- * void task1Function() {
- * Serial.println("Task 1 executing");
- * }
- *
- * void task2Function() {
- * Serial.println("Task 2 executing");
- * }
- *
- * Task myTask(1000, TASK_FOREVER, task1Function, &scheduler);
- * myTask.setCallback(task2Function); // Switch to different function
- * @endcode
- */
- __TASK_INLINE void setCallback(TaskCallback aCallback) ;
- /**
- * @brief Set the task enable lifecycle callback function
- *
- * Assigns a callback function that will be called when the task transitions
- * from disabled to enabled state. Enables custom initialization logic and
- * conditional enabling based on system conditions.
- *
- * @param aCallback Function pointer to the enable callback function.
- * Must have signature: bool onEnableFunction()
- * Return true to allow enabling, false to prevent it.
- *
- * @note Only available when _TASK_OO_CALLBACKS is NOT enabled (function pointer mode)
- * @note Called synchronously during enable() operation
- * @note Returning false from callback prevents task enabling
- * @note Setting nullptr removes the enable callback
- * @see TaskOnEnable, setOnDisable(), enable()
- * @since Version 2.0.0
- *
- * @par Example:
- * @code
- * bool checkSystemReady() {
- * return digitalRead(READY_PIN) == HIGH;
- * }
- *
- * Task myTask(1000, 10, mainCallback, &scheduler);
- * myTask.setOnEnable(checkSystemReady); // Conditional enabling
- * @endcode
- */
- __TASK_INLINE void setOnEnable(TaskOnEnable aCallback) ;
- /**
- * @brief Set the task disable lifecycle callback function
- *
- * Assigns a callback function that will be called when the task transitions
- * from enabled to disabled state. Enables custom cleanup logic and resource
- * management when the task is deactivated.
- *
- * @param aCallback Function pointer to the disable callback function.
- * Must have signature: void onDisableFunction()
- *
- * @note Only available when _TASK_OO_CALLBACKS is NOT enabled (function pointer mode)
- * @note Called synchronously during disable() operation
- * @note Called during automatic disable (iteration completion, errors)
- * @note Setting nullptr removes the disable callback
- * @see TaskOnDisable, setOnEnable(), disable()
- * @since Version 2.0.0
- *
- * @par Example:
- * @code
- * void cleanupTask() {
- * Serial.println("Task cleaning up");
- * // Release resources, save state, etc.
- * }
- *
- * Task myTask(1000, 5, mainCallback, &scheduler);
- * myTask.setOnDisable(cleanupTask); // Cleanup on disable
- * @endcode
- */
- __TASK_INLINE void setOnDisable(TaskOnDisable aCallback) ;
- /**
- * @brief Permanently switch to a new callback function
- *
- * Changes the task's callback function to the specified new function for all
- * subsequent executions. This enables state machine behavior and multi-phase
- * task processing within a single task object.
- *
- * @param aCallback Function pointer to the new callback function.
- * Must have signature: void newCallbackFunction()
- *
- * @note Only available when _TASK_OO_CALLBACKS is NOT enabled (function pointer mode)
- * @note Change takes effect immediately and is permanent
- * @note All future executions will use the new callback
- * @note Different from yieldOnce() which executes new callback only once
- * @see yieldOnce(), setCallback(), TaskCallback
- * @since Version 2.0.0
- *
- * @par Example:
- * @code
- * void phase1Callback() {
- * Serial.println("Phase 1");
- * // Switch to phase 2 after some condition
- * if (conditionMet()) {
- * myTask.yield(phase2Callback);
- * }
- * }
- *
- * void phase2Callback() {
- * Serial.println("Phase 2");
- * }
- * @endcode
- */
- __TASK_INLINE void yield(TaskCallback aCallback);
- /**
- * @brief Execute a callback function once, then disable the task
- *
- * Switches to the specified callback function for exactly one execution,
- * then automatically disables the task. Useful for one-time completion
- * logic, cleanup operations, or finalization steps.
- *
- * @param aCallback Function pointer to the callback function to execute once.
- * Must have signature: void onceCallbackFunction()
- *
- * @note Only available when _TASK_OO_CALLBACKS is NOT enabled (function pointer mode)
- * @note Task executes the new callback exactly once on next scheduler pass
- * @note Task automatically disables after the single execution
- * @note Original callback is not restored (task becomes inactive)
- * @note Useful for completion handlers and one-shot operations
- * @see yield(), setCallback(), TaskCallback
- * @since Version 2.0.0
- *
- * @par Example:
- * @code
- * void mainCallback() {
- * static int count = 0;
- * Serial.print("Main execution: ");
- * Serial.println(++count);
- *
- * if (count >= 5) {
- * myTask.yieldOnce(finalizationCallback);
- * }
- * }
- *
- * void finalizationCallback() {
- * Serial.println("Task completed - final cleanup");
- * // Task will automatically disable after this
- * }
- * @endcode
- */
- __TASK_INLINE void yieldOnce(TaskCallback aCallback);
- #endif // _TASK_OO_CALLBACKS
- /**
- * @brief Check if this is the first iteration
- * @return true if current pass is (or will be) a first iteration of the task
- */
- __TASK_INLINE bool isFirstIteration() ;
- /**
- * @brief Check if this is the last iteration
- * @return true if current pass is the last iteration (for tasks with limited iterations only)
- */
- __TASK_INLINE bool isLastIteration() ;
- #ifdef _TASK_TIMECRITICAL
- /**
- * @brief Get the execution overrun time in microseconds
- *
- * Returns the amount of time (in microseconds) that the task's execution
- * exceeded its scheduled interval. This measures how much longer the task
- * took to complete compared to its allocated time budget, helping identify
- * timing violations and performance bottlenecks.
- *
- * @return long Overrun time in microseconds. Positive values indicate the task
- * ran longer than its interval, negative values indicate it finished
- * early. Zero indicates the task completed exactly on schedule.
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Measured from scheduled execution time to actual completion time
- * @note Useful for real-time system analysis and performance optimization
- * @see getStartDelay(), _TASK_TIMECRITICAL
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void criticalTaskCallback() {
- * // Perform time-critical work
- * performCriticalOperation();
- *
- * // Check if we exceeded our time budget
- * long overrun = myTask.getOverrun();
- * if (overrun > 1000) { // More than 1ms overrun
- * Serial.print("Warning: Task overrun by ");
- * Serial.print(overrun);
- * Serial.println(" microseconds");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE long getOverrun() ;
- /**
- * @brief Get the task start delay in microseconds
- *
- * Returns the amount of time (in microseconds) between when the task was
- * scheduled to start and when it actually began execution. This measures
- * scheduler latency and helps identify system timing accuracy and load issues.
- *
- * @return long Start delay in microseconds. Positive values indicate the task
- * started later than scheduled, negative values indicate it started
- * early. Zero indicates perfect timing accuracy.
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Measured from scheduled start time to actual execution start time
- * @note High values may indicate system overload or scheduler inefficiency
- * @see getOverrun(), _TASK_TIMECRITICAL
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void timingAnalysisCallback() {
- * long startDelay = myTask.getStartDelay();
- * long overrun = myTask.getOverrun();
- *
- * Serial.print("Start delay: ");
- * Serial.print(startDelay);
- * Serial.print("us, Overrun: ");
- * Serial.print(overrun);
- * Serial.println("us");
- *
- * if (startDelay > 500) {
- * Serial.println("Warning: High scheduler latency detected");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE long getStartDelay() ;
- #endif // _TASK_TIMECRITICAL
- #ifdef _TASK_STATUS_REQUEST
- /**
- * @brief Wait for a StatusRequest to be signaled, then execute with new parameters
- *
- * Suspends this task until the specified StatusRequest is signaled by another task,
- * then reconfigures this task with new interval and iterations before resuming.
- * Enables sophisticated inter-task communication and coordination patterns.
- *
- * @param aStatusRequest Pointer to StatusRequest object to wait for
- * @param aInterval New execution interval in milliseconds (default: 0 = keep current)
- * @param aIterations New iteration count (default: 1 = single execution)
- *
- * @return bool True if wait was successful and task was reconfigured,
- * false if StatusRequest is invalid or operation failed
- *
- * @note Only available when _TASK_STATUS_REQUEST compile-time option is enabled
- * @note Task becomes inactive until StatusRequest is signaled
- * @note StatusRequest must be signaled by another task's completion
- * @note Interval of 0 keeps current task interval unchanged
- * @see waitForDelayed(), getStatusRequest(), StatusRequest
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * Task task1(1000, TASK_FOREVER, task1Callback, &scheduler);
- * Task task2(500, 1, task2Callback, &scheduler);
- *
- * void task1Callback() {
- * // Wait for task2 to complete, then run every 200ms for 5 iterations
- * if (task1.waitFor(task2.getStatusRequest(), 200, 5)) {
- * Serial.println("Task1 resumed after task2 completion");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE bool waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
- /**
- * @brief Wait for a StatusRequest with delay, then execute with new parameters
- *
- * Similar to waitFor() but introduces an additional delay before the task
- * becomes eligible for execution after the StatusRequest is signaled.
- * Useful for staggered execution and preventing simultaneous task activation.
- *
- * @param aStatusRequest Pointer to StatusRequest object to wait for
- * @param aInterval New execution interval in milliseconds (default: 0 = keep current)
- * @param aIterations New iteration count (default: 1 = single execution)
- *
- * @return bool True if wait was successful and task was reconfigured,
- * false if StatusRequest is invalid or operation failed
- *
- * @note Only available when _TASK_STATUS_REQUEST compile-time option is enabled
- * @note Adds scheduling delay after StatusRequest is signaled
- * @note Prevents immediate execution, allowing for staggered task activation
- * @note Interval of 0 keeps current task interval unchanged
- * @see waitFor(), getStatusRequest(), StatusRequest
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void coordinatorCallback() {
- * // Wait for sensor task, then start processing with 1 second delay
- * if (processingTask.waitForDelayed(sensorTask.getStatusRequest(), 1000, 10)) {
- * Serial.println("Processing will start 1 second after sensor completion");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE bool waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
- /**
- * @brief Get the external StatusRequest object for this task
- *
- * Returns a pointer to the StatusRequest object that other tasks can use
- * to wait for this task's completion. This enables the creation of task
- * dependency chains and sophisticated coordination patterns.
- *
- * @return StatusRequest* Pointer to the task's external StatusRequest object,
- * or nullptr if StatusRequest functionality is not available
- *
- * @note Only available when _TASK_STATUS_REQUEST compile-time option is enabled
- * @note External StatusRequest is signaled when task completes its iterations
- * @note Used by other tasks in waitFor() and waitForDelayed() calls
- * @note Different from getInternalStatusRequest() which is used for internal coordination
- * @see getInternalStatusRequest(), waitFor(), StatusRequest
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * Task producerTask(1000, 5, producerCallback, &scheduler);
- * Task consumerTask(100, 1, consumerCallback, &scheduler);
- *
- * void setupTasks() {
- * // Consumer waits for producer to complete
- * StatusRequest* producerStatus = producerTask.getStatusRequest();
- * consumerTask.waitFor(producerStatus, 500, TASK_FOREVER);
- * }
- * @endcode
- */
- __TASK_INLINE StatusRequest* getStatusRequest() ;
- /**
- * @brief Get the internal StatusRequest object for this task
- *
- * Returns a pointer to the internal StatusRequest object used for advanced
- * task coordination patterns within the same task or tightly coupled task groups.
- * Provides finer control over task signaling and coordination mechanisms.
- *
- * @return StatusRequest* Pointer to the task's internal StatusRequest object,
- * or nullptr if StatusRequest functionality is not available
- *
- * @note Only available when _TASK_STATUS_REQUEST compile-time option is enabled
- * @note Internal StatusRequest provides advanced coordination capabilities
- * @note Used for complex task orchestration and state machine patterns
- * @note Separate from external StatusRequest for different coordination levels
- * @see getStatusRequest(), waitFor(), StatusRequest
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void complexCoordinationCallback() {
- * StatusRequest* internalStatus = myTask.getInternalStatusRequest();
- * // Use internal status for advanced coordination
- * otherTask.waitForDelayed(internalStatus, 100, 1);
- * }
- * @endcode
- */
- __TASK_INLINE StatusRequest* getInternalStatusRequest() ;
- #endif // _TASK_STATUS_REQUEST
- #ifdef _TASK_WDT_IDS
- /**
- * @brief Set the watchdog timer ID for this task
- *
- * Assigns a unique identifier to the task for watchdog timer monitoring.
- * The ID is used by external watchdog systems to track task execution
- * and detect hung or malfunctioning tasks in mission-critical applications.
- *
- * @param aID Unique identifier for watchdog monitoring (typically 0-255 range)
- *
- * @note Only available when _TASK_WDT_IDS compile-time option is enabled
- * @note ID should be unique across all tasks in the system
- * @note Used in conjunction with external watchdog hardware/software
- * @note Essential for safety-critical and mission-critical applications
- * @see getId(), setControlPoint(), _TASK_WDT_IDS
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * Task criticalTask(1000, TASK_FOREVER, criticalCallback, &scheduler);
- * Task monitorTask(5000, TASK_FOREVER, monitorCallback, &scheduler);
- *
- * void setup() {
- * criticalTask.setId(1); // Critical system task
- * monitorTask.setId(2); // System monitor task
- * }
- *
- * void criticalCallback() {
- * // Reset watchdog for this task ID
- * resetWatchdog(criticalTask.getId());
- * }
- * @endcode
- */
- __TASK_INLINE void setId(unsigned int aID) ;
- /**
- * @brief Get the watchdog timer ID for this task
- *
- * Returns the unique identifier assigned to this task for watchdog monitoring.
- * Used by watchdog systems and monitoring code to identify which task is
- * currently executing or has failed to respond.
- *
- * @return unsigned int The task's watchdog ID, or 0 if no ID has been set
- *
- * @note Only available when _TASK_WDT_IDS compile-time option is enabled
- * @note Returns the ID set by setId(), or 0 for uninitialized tasks
- * @note Used for watchdog reset operations and task identification
- * @see setId(), getControlPoint(), _TASK_WDT_IDS
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void watchdogResetCallback() {
- * unsigned int taskId = myTask.getId();
- * if (taskId > 0) {
- * // Reset watchdog for this specific task
- * resetWatchdogTimer(taskId);
- * Serial.print("Watchdog reset for task ID: ");
- * Serial.println(taskId);
- * }
- * }
- * @endcode
- */
- __TASK_INLINE unsigned int getId() ;
- /**
- * @brief Set the control point identifier for this task
- *
- * Assigns a control point identifier used for fine-grained execution monitoring
- * and debugging. Control points can mark specific execution phases or critical
- * sections within task callbacks for detailed system analysis.
- *
- * @param aPoint Control point identifier (application-defined meaning)
- *
- * @note Only available when _TASK_WDT_IDS compile-time option is enabled
- * @note Control points provide execution phase tracking within tasks
- * @note Used for debugging, profiling, and fine-grained monitoring
- * @note Meaning and usage are application-specific
- * @see getControlPoint(), setId(), _TASK_WDT_IDS
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void complexTaskCallback() {
- * myTask.setControlPoint(1); // Phase 1: Sensor reading
- * readSensors();
- *
- * myTask.setControlPoint(2); // Phase 2: Data processing
- * processData();
- *
- * myTask.setControlPoint(3); // Phase 3: Output generation
- * generateOutput();
- *
- * myTask.setControlPoint(0); // Phase complete
- * }
- * @endcode
- */
- __TASK_INLINE void setControlPoint(unsigned int aPoint) ;
- /**
- * @brief Get the current control point identifier for this task
- *
- * Returns the current control point identifier, indicating which execution
- * phase or critical section the task is currently in or last executed.
- * Useful for debugging hung tasks and execution flow analysis.
- *
- * @return unsigned int Current control point identifier, or 0 if none set
- *
- * @note Only available when _TASK_WDT_IDS compile-time option is enabled
- * @note Returns the most recent control point set by setControlPoint()
- * @note Used for debugging and execution phase identification
- * @note Can help identify where tasks hang or fail
- * @see setControlPoint(), getId(), _TASK_WDT_IDS
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void monitorTaskCallback() {
- * unsigned int controlPoint = criticalTask.getControlPoint();
- * unsigned long lastRun = criticalTask.getRunCounter();
- *
- * if (lastRun == previousRunCount && controlPoint != 0) {
- * Serial.print("Critical task hung at control point: ");
- * Serial.println(controlPoint);
- * // Take corrective action
- * }
- * previousRunCount = lastRun;
- * }
- * @endcode
- */
- __TASK_INLINE unsigned int getControlPoint() ;
- #endif // _TASK_WDT_IDS
- #ifdef _TASK_LTS_POINTER
- /**
- * @brief Set the Local Task Storage (LTS) pointer for this task
- *
- * Assigns a pointer to task-specific data storage that persists across
- * task executions. This enables tasks to maintain state, store working
- * data, or reference external resources without using global variables.
- *
- * @param aPtr Pointer to task-local storage area (any data type)
- *
- * @note Only available when _TASK_LTS_POINTER compile-time option is enabled
- * @note Pointer can reference any data structure or object
- * @note Memory management is application responsibility
- * @note Enables object-oriented patterns and data encapsulation
- * @see getLtsPointer(), _TASK_LTS_POINTER
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * struct TaskData {
- * int counter;
- * float average;
- * bool initialized;
- * };
- *
- * TaskData myTaskData = {0, 0.0, false};
- * Task dataTask(1000, TASK_FOREVER, dataCallback, &scheduler);
- *
- * void setup() {
- * dataTask.setLtsPointer(&myTaskData);
- * }
- *
- * void dataCallback() {
- * TaskData* data = (TaskData*)dataTask.getLtsPointer();
- * if (data) {
- * data->counter++;
- * // Use task-specific data
- * }
- * }
- * @endcode
- */
- __TASK_INLINE void setLtsPointer(void *aPtr) ;
- /**
- * @brief Get the Local Task Storage (LTS) pointer for this task
- *
- * Returns the pointer to task-specific data storage previously set with
- * setLtsPointer(). Enables tasks to access their persistent data without
- * relying on global variables or external storage mechanisms.
- *
- * @return void* Pointer to task-local storage, or nullptr if none set
- *
- * @note Only available when _TASK_LTS_POINTER compile-time option is enabled
- * @note Returned pointer must be cast to appropriate data type
- * @note Returns nullptr if no LTS pointer has been set
- * @note Enables clean data encapsulation and object-oriented patterns
- * @see setLtsPointer(), _TASK_LTS_POINTER
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * struct SensorData {
- * float temperature;
- * float humidity;
- * unsigned long lastReading;
- * };
- *
- * void sensorCallback() {
- * SensorData* data = (SensorData*)sensorTask.getLtsPointer();
- * if (data) {
- * data->temperature = readTemperature();
- * data->humidity = readHumidity();
- * data->lastReading = millis();
- *
- * Serial.print("Temp: ");
- * Serial.print(data->temperature);
- * Serial.print("°C, Humidity: ");
- * Serial.print(data->humidity);
- * Serial.println("%");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE void* getLtsPointer() ;
- #endif // _TASK_LTS_POINTER
- #ifdef _TASK_EXPOSE_CHAIN
- /**
- * @brief Get pointer to the previous task in the scheduler's task chain
- *
- * Returns a pointer to the task that precedes this task in the scheduler's
- * internal linked list. This enables task chain traversal, debugging, and
- * advanced task management operations for custom scheduler behaviors.
- *
- * @return Task* Pointer to the previous task in the chain, or nullptr if:
- * - This is the first task in the chain
- * - Task is not currently registered with a scheduler
- * - Task chain is empty
- *
- * @note Only available when _TASK_EXPOSE_CHAIN compile-time option is enabled
- * @note Exposes internal scheduler data structure for advanced operations
- * @note Chain order may not correlate with execution order (depends on timing)
- * @note Useful for debugging, custom algorithms, and chain analysis
- * @warning Direct chain manipulation can corrupt scheduler state
- * @see getNextTask(), _TASK_EXPOSE_CHAIN
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void analyzeTaskChain(Task& startTask) {
- * Task* current = &startTask;
- * int position = 0;
- *
- * // Walk backwards through the chain
- * while (current->getPreviousTask() != nullptr) {
- * current = current->getPreviousTask();
- * position++;
- * }
- *
- * Serial.print("Task is at position ");
- * Serial.print(position);
- * Serial.println(" from chain start");
- * }
- *
- * void debugTaskChain(Scheduler& scheduler) {
- * // Find chain relationships for debugging
- * Serial.println("Task Chain Analysis:");
- * // Implementation would traverse and analyze the chain
- * }
- * @endcode
- */
- __TASK_INLINE Task* getPreviousTask() { return iPrev; };
- /**
- * @brief Get pointer to the next task in the scheduler's task chain
- *
- * Returns a pointer to the task that follows this task in the scheduler's
- * internal linked list. This enables forward chain traversal, task enumeration,
- * and advanced scheduler analysis for custom task management operations.
- *
- * @return Task* Pointer to the next task in the chain, or nullptr if:
- * - This is the last task in the chain
- * - Task is not currently registered with a scheduler
- * - Task chain is empty
- *
- * @note Only available when _TASK_EXPOSE_CHAIN compile-time option is enabled
- * @note Exposes internal scheduler data structure for advanced operations
- * @note Chain order is registration order, not execution priority
- * @note Useful for iteration, monitoring, and custom scheduler algorithms
- * @warning Direct chain manipulation can corrupt scheduler state
- * @see getPreviousTask(), _TASK_EXPOSE_CHAIN
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void printAllTasks(Task& firstTask) {
- * Task* current = &firstTask;
- * int taskCount = 0;
- *
- * Serial.println("=== Task Chain Report ===");
- * while (current != nullptr) {
- * taskCount++;
- * Serial.print("Task ");
- * Serial.print(taskCount);
- * Serial.print(": Enabled=");
- * Serial.print(current->isEnabled() ? "YES" : "NO");
- * Serial.print(", Interval=");
- * Serial.print(current->getInterval());
- * Serial.print("ms, Iterations=");
- * Serial.println(current->getIterations());
- *
- * current = current->getNextTask();
- * }
- * Serial.print("Total tasks: ");
- * Serial.println(taskCount);
- * }
- *
- * int countEnabledTasks(Task& anyTask) {
- * // Find start of chain
- * Task* start = &anyTask;
- * while (start->getPreviousTask() != nullptr) {
- * start = start->getPreviousTask();
- * }
- *
- * // Count enabled tasks
- * int enabledCount = 0;
- * Task* current = start;
- * while (current != nullptr) {
- * if (current->isEnabled()) {
- * enabledCount++;
- * }
- * current = current->getNextTask();
- * }
- * return enabledCount;
- * }
- * @endcode
- */
- __TASK_INLINE Task* getNextTask() { return iNext; };
- #endif // _TASK_EXPOSE_CHAIN
- _TASK_SCOPE:
- __TASK_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
- };
- /**
- * @class Scheduler
- * @brief Task scheduler for cooperative multitasking
- *
- * @details The Scheduler class manages the execution of tasks in a cooperative multitasking environment.
- * It maintains a chain of tasks and executes them according to their schedules and priorities.
- *
- * Key features:
- * - Cooperative multitasking (non-preemptive)
- * - Task chain management
- * - Priority layer support
- * - Sleep mode support for power saving
- * - Thread safety options
- * - Performance monitoring
- *
- * The scheduler executes Tasks' callback methods in the order the tasks were added to the chain,
- * from first to last. Scheduler stops and exits after processing the chain once in order to allow
- * other statements in the main code of loop() method to run. This is referred to as a "scheduling pass".
- *
- * @note Normally, there is no need to have any other statements in the loop() method other than
- * the Scheduler's execute() method.
- *
- * @see Task, StatusRequest
- */
- class Scheduler {
- friend class Task;
- public:
- /**
- * @brief Default constructor
- * @details Creates task scheduler with default parameters and an empty task queue.
- */
- __TASK_INLINE Scheduler();
- /**
- * @brief Initialize the scheduler
- * @details Initializes the task queue and scheduler parameters. Executed as part of constructor,
- * so doesn't need to be explicitly called after creation.
- *
- * @note By default scheduler is allowed to put processor to IDLE sleep mode. If this behavior
- * was changed via allowSleep() method, init() will NOT reset the sleep parameter.
- */
- __TASK_INLINE void init();
- /**
- * @brief Add task to execution chain
- * @param aTask Reference to task to be added
- * @details Adds task to the execution queue (or chain) of tasks by appending it to the end
- * of the chain. If two tasks are scheduled for execution, the sequence will match the order
- * in which tasks were appended to the chain.
- *
- * @note Currently, changing the execution sequence in a chain dynamically is not supported.
- * If you need to reorder the chain sequence – initialize the scheduler and re-add the tasks
- * in a different order.
- */
- __TASK_INLINE void addTask(Task& aTask);
- /**
- * @brief Delete task from execution chain
- * @param aTask Reference to task to be deleted
- * @details Deletes task from the execution chain. The chain of remaining tasks is linked
- * together. It is not required to delete a task from the chain. A disabled task will not
- * be executed anyway, but you save a few microseconds per scheduling pass by deleting it.
- */
- __TASK_INLINE void deleteTask(Task& aTask);
- /**
- * @brief Pause the scheduler
- * @details Temporarily suspends all task execution. Tasks remain in their current state
- * but will not be executed until resume() is called.
- */
- __TASK_INLINE void pause() { iPaused = true; };
- /**
- * @brief Resume the scheduler
- * @details Resumes task execution after pause().
- */
- __TASK_INLINE void resume() { iPaused = false; };
- /**
- * @brief Enable the scheduler
- * @details Enables the scheduler for task execution.
- */
- __TASK_INLINE void enable() { iEnabled = true; };
- /**
- * @brief Disable the scheduler
- * @details Disables the scheduler, preventing any task execution.
- */
- __TASK_INLINE void disable() { iEnabled = false; };
- #ifdef _TASK_PRIORITY
- /**
- * @brief Disable all tasks (with priority support)
- * @param aRecursive If true (default), disable higher priority tasks as well
- * @details Convenient method to disable majority of tasks.
- */
- __TASK_INLINE void disableAll(bool aRecursive = true);
- /**
- * @brief Enable all tasks (with priority support)
- * @param aRecursive If true (default), enable higher priority tasks as well
- * @details Convenient method to enable majority of tasks.
- */
- __TASK_INLINE void enableAll(bool aRecursive = true);
- /**
- * @brief Set all tasks to start immediately (with priority support)
- * @param aRecursive If true (default), affect higher priority tasks as well
- * @details Sets ALL active tasks to start execution immediately. Should be placed
- * at the end of setup() method to prevent task execution race due to long running
- * setup tasks. Any tasks which should execute after a delay should be explicitly
- * delayed after call to startNow() method.
- */
- __TASK_INLINE void startNow(bool aRecursive = true);
- #else
- /**
- * @brief Disable all tasks
- * @details Convenient method to disable majority of tasks.
- */
- __TASK_INLINE void disableAll();
- /**
- * @brief Enable all tasks
- * @details Convenient method to enable majority of tasks.
- */
- __TASK_INLINE void enableAll();
- /**
- * @brief Set all tasks to start immediately
- * @details Sets ALL active tasks to start execution immediately. Should be placed
- * at the end of setup() method to prevent task execution race due to long running
- * setup tasks.
- */
- __TASK_INLINE void startNow();
- #endif
- /**
- * @brief Execute one scheduling pass
- * @return true if none of the tasks' callback methods was invoked (true = idle run)
- * @details Executes one scheduling pass, including (in case of the base priority scheduler)
- * end-of-pass sleep. This method should be placed inside the loop() method of the sketch.
- * Since execute exits after every pass, you can put additional statements after execute
- * inside the loop().
- *
- * If layered task prioritization is enabled, all higher priority tasks will be evaluated
- * and invoked by the base execute() method. There is no need to call execute() of the
- * higher priority schedulers explicitly.
- *
- * The execute method performs the following steps:
- * 1. Call higher priority scheduler's execute method, if provided
- * 2. Ignore task completely if it is disabled
- * 3. Disable task if it ran out of iterations (calling OnDisable, if necessary)
- * 4. Check if task is waiting on a StatusRequest object, and make appropriate scheduling arrangements
- * 5. Perform necessary timing calculations
- * 6. Invoke task's callback method, if it is time to do so, and one is provided
- * 7. Put microcontroller to sleep (if requested and supported) if none of the tasks were invoked
- *
- * @note Schedule-related calculations are performed prior to task's callback method invocation.
- * This allows tasks to manipulate their runtime parameters (like execution interval) directly.
- */
- __TASK_INLINE bool execute();
- /**
- * @brief Get reference to currently executing task (deprecated)
- * @return Reference to the currently active task
- * @deprecated Use getCurrentTask() instead
- */
- __TASK_INLINE Task& currentTask() ;
- /**
- * @brief Get pointer to currently executing task
- * @return Pointer to the currently active task
- * @details Returns pointer to the task currently executing via execute() loop OR for
- * OnEnable and OnDisable methods, pointer to the task being enabled or disabled.
- * This distinction is important because one task can activate another.
- * Could be used by callback methods to identify which Task invoked this callback method.
- */
- __TASK_INLINE Task* getCurrentTask() ;
- /**
- * @brief Get time until next iteration of a task
- * @param aTask Reference to the task to query
- * @return Number of milliseconds (or microseconds) until next scheduled iteration
- * @details Returns 0 if next iteration is already due (or overdue).
- * Returns -1 if a Task is not active or waiting on an event, and next iteration
- * runtime cannot be determined.
- */
- __TASK_INLINE long timeUntilNextIteration(Task& aTask);
- /**
- * @brief Get number of active tasks
- * @return Number of currently active (enabled) tasks
- */
- __TASK_INLINE unsigned long getActiveTasks() { return iActiveTasks; }
- /**
- * @brief Get total number of tasks
- * @return Total number of tasks in the scheduler
- */
- __TASK_INLINE unsigned long getTotalTasks() { return iTotalTasks; }
- /**
- * @brief Get number of invoked tasks
- * @return Number of tasks that were invoked during the last execute() pass
- */
- __TASK_INLINE unsigned long getInvokedTasks() { return iInvokedTasks; }
- #ifdef _TASK_TICKLESS
- /**
- * @brief Get next run time (tickless mode)
- * @return Next scheduled run time
- * @details Available only when compiled with _TASK_TICKLESS support.
- */
- __TASK_INLINE unsigned long getNextRun() { return iNextRun; }
- #endif
- #ifdef _TASK_SLEEP_ON_IDLE_RUN
- /**
- * @brief Enable or disable sleep mode during idle scheduler cycles
- *
- * Controls whether the scheduler should enter sleep mode when no tasks
- * are ready for execution. Sleep mode reduces power consumption by
- * halting CPU execution until the next task is scheduled to run.
- *
- * @param aState True to enable sleep mode (default), false to disable
- *
- * @note Only available when _TASK_SLEEP_ON_IDLE_RUN compile-time option is enabled
- * @note Sleep is only activated when all tasks return false from their callbacks
- * @note Tasks returning true (productive execution) prevent sleep on next cycle
- * @note Custom sleep method can be set with setSleepMethod()
- * @see setSleepMethod(), _TASK_SLEEP_ON_IDLE_RUN
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * Scheduler powerEfficientScheduler;
- *
- * void setup() {
- * // Enable power-saving sleep mode
- * powerEfficientScheduler.allowSleep(true);
- *
- * // Custom sleep implementation
- * powerEfficientScheduler.setSleepMethod(customSleepCallback);
- * }
- *
- * void customSleepCallback(unsigned long aTimeToSleep) {
- * if (aTimeToSleep > 1000) {
- * // Deep sleep for longer periods
- * ESP.deepSleep(aTimeToSleep * 1000); // Convert to microseconds
- * } else {
- * // Light sleep for short periods
- * delay(aTimeToSleep);
- * }
- * }
- * @endcode
- */
- __TASK_INLINE void allowSleep(bool aState = true);
- /**
- * @brief Set custom sleep implementation callback
- *
- * Assigns a custom callback function that will be called when the scheduler
- * enters sleep mode. This allows for platform-specific power management
- * implementations, such as deep sleep modes on ESP32 or low-power modes
- * on Arduino boards.
- *
- * @param aCallback Function pointer to sleep callback with signature:
- * void sleepCallback(unsigned long sleepTime)
- * where sleepTime is in milliseconds
- *
- * @note Only available when _TASK_SLEEP_ON_IDLE_RUN compile-time option is enabled
- * @note Sleep callback receives the calculated sleep duration in milliseconds
- * @note Default implementation uses delay() if no custom callback is set
- * @note Callback should implement appropriate power management for the platform
- * @see allowSleep(), SleepCallback, _TASK_SLEEP_ON_IDLE_RUN
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void arduinoSleep(unsigned long sleepTime) {
- * // Arduino-specific power management
- * if (sleepTime > 100) {
- * // Use watchdog timer for longer sleeps
- * set_sleep_mode(SLEEP_MODE_PWR_DOWN);
- * sleep_enable();
- * sleep_mode();
- * sleep_disable();
- * } else {
- * delay(sleepTime);
- * }
- * }
- *
- * void esp32Sleep(unsigned long sleepTime) {
- * // ESP32-specific power management
- * if (sleepTime > 1000) {
- * esp_sleep_enable_timer_wakeup(sleepTime * 1000ULL);
- * esp_light_sleep_start();
- * } else {
- * delayMicroseconds(sleepTime * 1000);
- * }
- * }
- *
- * scheduler.setSleepMethod(esp32Sleep);
- * @endcode
- */
- __TASK_INLINE void setSleepMethod( SleepCallback aCallback );
- #endif // _TASK_SLEEP_ON_IDLE_RUN
- #ifdef _TASK_LTS_POINTER
- /**
- * @brief Get Local Task Storage pointer of currently executing task
- *
- * Returns the LTS (Local Task Storage) pointer of the task that is
- * currently being executed by the scheduler. This provides access to
- * task-specific data from within the scheduler context or shared utilities.
- *
- * @return void* Pointer to the current task's local storage, or nullptr if:
- * - No task is currently executing
- * - Current task has no LTS pointer set
- * - Called outside of task execution context
- *
- * @note Only available when _TASK_LTS_POINTER compile-time option is enabled
- * @note Must be called from within task execution context for valid results
- * @note Returned pointer must be cast to appropriate data type
- * @note Useful for shared utilities that need access to current task data
- * @see Task::setLtsPointer(), Task::getLtsPointer(), _TASK_LTS_POINTER
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * struct TaskData {
- * int sensorValue;
- * float average;
- * bool alertFlag;
- * };
- *
- * void sharedUtilityFunction() {
- * TaskData* currentData = (TaskData*)scheduler.currentLts();
- * if (currentData) {
- * // Access current task's data
- * Serial.print("Current task sensor value: ");
- * Serial.println(currentData->sensorValue);
- *
- * if (currentData->sensorValue > THRESHOLD) {
- * currentData->alertFlag = true;
- * }
- * }
- * }
- *
- * void taskCallback() {
- * // Task-specific work
- * readSensors();
- *
- * // Call shared utility that accesses current task's LTS
- * sharedUtilityFunction();
- * }
- * @endcode
- */
- __TASK_INLINE void* currentLts();
- #endif // _TASK_LTS_POINTER
- #ifdef _TASK_TIMECRITICAL
- /**
- * @brief Check if any task execution overran its allocated time
- *
- * Returns whether any task in the current execution cycle exceeded its
- * scheduled interval time. This provides system-wide timing violation
- * detection for real-time system monitoring and performance analysis.
- *
- * @return bool True if any task overran its allocated time, false otherwise
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Checks for timing violations across all tasks in the scheduler
- * @note Useful for system-wide real-time performance monitoring
- * @note Should be checked after each scheduler execution cycle
- * @see Task::getOverrun(), getCpuLoadTotal(), _TASK_TIMECRITICAL
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void loop() {
- * scheduler.execute();
- *
- * // Check for system-wide timing violations
- * if (scheduler.isOverrun()) {
- * Serial.println("WARNING: System overrun detected!");
- *
- * // Log CPU load statistics
- * unsigned long cpuLoad = scheduler.getCpuLoadTotal();
- * Serial.print("CPU Load: ");
- * Serial.print(cpuLoad);
- * Serial.println("%");
- *
- * // Take corrective action
- * if (cpuLoad > 90) {
- * // Reduce system load
- * disableNonCriticalTasks();
- * }
- * }
- * }
- * @endcode
- */
- __TASK_INLINE bool isOverrun();
- /**
- * @brief Reset CPU load measurement counters
- *
- * Resets the internal counters used for CPU load calculation, providing
- * a fresh measurement baseline. This allows for periodic CPU load monitoring
- * and performance analysis over specific time intervals.
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Resets both cycle time and idle time counters
- * @note Should be called before starting a new measurement period
- * @note Useful for periodic performance monitoring and load analysis
- * @see getCpuLoadTotal(), getCpuLoadCycle(), getCpuLoadIdle()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void performanceMonitor() {
- * static unsigned long lastReset = 0;
- * unsigned long now = millis();
- *
- * // Measure CPU load every 10 seconds
- * if (now - lastReset > 10000) {
- * unsigned long cpuLoad = scheduler.getCpuLoadTotal();
- * unsigned long cycleTime = scheduler.getCpuLoadCycle();
- * unsigned long idleTime = scheduler.getCpuLoadIdle();
- *
- * Serial.print("10s Performance Report - CPU Load: ");
- * Serial.print(cpuLoad);
- * Serial.print("%, Cycle: ");
- * Serial.print(cycleTime);
- * Serial.print("us, Idle: ");
- * Serial.print(idleTime);
- * Serial.println("us");
- *
- * // Reset for next measurement period
- * scheduler.cpuLoadReset();
- * lastReset = now;
- * }
- * }
- * @endcode
- */
- __TASK_INLINE void cpuLoadReset();
- /**
- * @brief Get total CPU cycle time in microseconds
- *
- * Returns the cumulative time spent in CPU cycles (active execution)
- * since the last reset. This measures the total processing time used
- * by all tasks and scheduler overhead.
- *
- * @return unsigned long Total CPU cycle time in microseconds
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Includes task execution time and scheduler overhead
- * @note Used in conjunction with getCpuLoadIdle() for load calculation
- * @note Accumulates until reset with cpuLoadReset()
- * @see getCpuLoadIdle(), getCpuLoadTotal(), cpuLoadReset()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void detailedPerformanceAnalysis() {
- * unsigned long cycleTime = scheduler.getCpuLoadCycle();
- * unsigned long idleTime = scheduler.getCpuLoadIdle();
- * unsigned long totalTime = cycleTime + idleTime;
- *
- * if (totalTime > 0) {
- * float cpuUtilization = (float)cycleTime / totalTime * 100.0;
- * float idlePercentage = (float)idleTime / totalTime * 100.0;
- *
- * Serial.print("Detailed Analysis - Active: ");
- * Serial.print(cpuUtilization, 2);
- * Serial.print("%, Idle: ");
- * Serial.print(idlePercentage, 2);
- * Serial.print("%, Total time: ");
- * Serial.print(totalTime);
- * Serial.println("us");
- * }
- * }
- * @endcode
- */
- __TASK_INLINE unsigned long getCpuLoadCycle(){ return iCPUCycle; };
- /**
- * @brief Get total CPU idle time in microseconds
- *
- * Returns the cumulative time spent in idle state (no tasks executing)
- * since the last reset. This measures the total time the CPU was
- * available but not processing tasks.
- *
- * @return unsigned long Total CPU idle time in microseconds
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Includes time spent waiting for next task execution
- * @note Used in conjunction with getCpuLoadCycle() for load calculation
- * @note Accumulates until reset with cpuLoadReset()
- * @see getCpuLoadCycle(), getCpuLoadTotal(), cpuLoadReset()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void powerManagementAnalysis() {
- * unsigned long idleTime = scheduler.getCpuLoadIdle();
- * unsigned long cycleTime = scheduler.getCpuLoadCycle();
- *
- * // Calculate power saving potential
- * if (idleTime > cycleTime) {
- * float powerSavingPotential = (float)idleTime / (idleTime + cycleTime) * 100.0;
- *
- * Serial.print("Power saving potential: ");
- * Serial.print(powerSavingPotential, 1);
- * Serial.println("%");
- *
- * if (powerSavingPotential > 50.0) {
- * Serial.println("Consider enabling sleep mode for better power efficiency");
- * }
- * }
- * }
- * @endcode
- */
- __TASK_INLINE unsigned long getCpuLoadIdle() { return iCPUIdle; };
- /**
- * @brief Get total CPU load percentage
- *
- * Calculates and returns the CPU load as a percentage based on the ratio
- * of active cycle time to total time (cycle + idle). This provides a
- * normalized measure of system utilization for performance monitoring.
- *
- * @return unsigned long CPU load percentage (0-100)
- *
- * @note Only available when _TASK_TIMECRITICAL compile-time option is enabled
- * @note Returns percentage of time spent in active execution vs idle
- * @note Calculation: (cycleTime / (cycleTime + idleTime)) * 100
- * @note Returns 0 if no measurements have been taken
- * @see getCpuLoadCycle(), getCpuLoadIdle(), cpuLoadReset()
- * @since Version 3.0.0
- *
- * @par Example:
- * @code
- * void systemHealthMonitor() {
- * unsigned long cpuLoad = scheduler.getCpuLoadTotal();
- *
- * // System health thresholds
- * if (cpuLoad > 95) {
- * Serial.println("CRITICAL: CPU load extremely high!");
- * // Emergency measures
- * disableNonEssentialTasks();
- * } else if (cpuLoad > 80) {
- * Serial.println("WARNING: High CPU load detected");
- * // Performance optimization
- * optimizeTaskIntervals();
- * } else if (cpuLoad < 10) {
- * Serial.println("INFO: Low CPU load - power optimization opportunity");
- * // Enable power saving features
- * scheduler.allowSleep(true);
- * }
- *
- * // Log current status
- * Serial.print("Current CPU Load: ");
- * Serial.print(cpuLoad);
- * Serial.println("%");
- * }
- * @endcode
- */
- __TASK_INLINE unsigned long getCpuLoadTotal();
- #endif // _TASK_TIMECRITICAL
- #ifdef _TASK_PRIORITY
- /**
- * @brief Sets a higher priority scheduler for priority-based task scheduling
- *
- * This method establishes a hierarchical relationship between schedulers, allowing
- * the current scheduler to defer execution to a higher priority scheduler when needed.
- * This enables multi-level priority scheduling where critical tasks can preempt
- * normal task execution.
- *
- * @param aScheduler Pointer to the higher priority scheduler to associate with this scheduler.
- * Pass nullptr to remove the high priority scheduler association.
- *
- * @note This method is only available when _TASK_PRIORITY compilation option is enabled.
- * @note The high priority scheduler should be executed more frequently than this scheduler
- * to ensure priority-based preemption works correctly.
- * @note Circular priority relationships should be avoided to prevent infinite loops.
- *
- * @see currentScheduler()
- * @see _TASK_PRIORITY
- *
- * Example usage:
- * @code
- * Scheduler highPriorityScheduler;
- * Scheduler normalScheduler;
- *
- * // Set up priority relationship
- * normalScheduler.setHighPriorityScheduler(&highPriorityScheduler);
- *
- * // In main loop, execute high priority first
- * highPriorityScheduler.execute();
- * normalScheduler.execute();
- * @endcode
- */
- __TASK_INLINE void setHighPriorityScheduler(Scheduler* aScheduler);
- /**
- * @brief Returns a reference to the currently executing scheduler
- *
- * This static method provides access to the scheduler that is currently executing tasks.
- * It's primarily used internally by the library to maintain context during task execution
- * and to support priority-based scheduling operations.
- *
- * @return Reference to the currently active scheduler instance
- *
- * @note This method is only available when _TASK_PRIORITY compilation option is enabled.
- * @note This is a static method that can be called without a scheduler instance.
- * @note The returned reference is valid only during task execution context.
- *
- * @warning Do not store the returned reference for long-term use as the current
- * scheduler context changes during execution.
- *
- * @see setHighPriorityScheduler()
- * @see _TASK_PRIORITY
- *
- * Example usage:
- * @code
- * void taskCallback() {
- * // Get reference to the scheduler executing this task
- * Scheduler& currentSched = Scheduler::currentScheduler();
- *
- * // Access scheduler information
- * Serial.print("Active tasks: ");
- * Serial.println(currentSched.size());
- * }
- * @endcode
- */
- __TASK_INLINE static Scheduler& currentScheduler() { return *(iCurrentScheduler); };
- #endif // _TASK_PRIORITY
- #ifdef _TASK_EXPOSE_CHAIN
- /**
- * @brief Returns a pointer to the first task in the scheduler's task chain
- *
- * This method provides direct access to the first task in the internal linked list
- * of tasks managed by this scheduler. It's primarily used for advanced task chain
- * manipulation, debugging, and custom iteration over all tasks.
- *
- * @return Pointer to the first task in the chain, or nullptr if no tasks are registered
- *
- * @note This method is only available when _TASK_EXPOSE_CHAIN compilation option is enabled.
- * @note The returned pointer should be treated as read-only to avoid corrupting the task chain.
- * @note Tasks are stored in a doubly-linked list internally.
- *
- * @warning Direct manipulation of the task chain can lead to undefined behavior.
- * Use the standard addTask() and deleteTask() methods instead.
- *
- * @see getLastTask()
- * @see addTask()
- * @see deleteTask()
- * @see _TASK_EXPOSE_CHAIN
- *
- * Example usage:
- * @code
- * Scheduler ts;
- * Task t1, t2, t3;
- *
- * ts.addTask(t1);
- * ts.addTask(t2);
- * ts.addTask(t3);
- *
- * // Iterate through all tasks
- * Task* current = ts.getFirstTask();
- * while (current != nullptr) {
- * Serial.print("Task ID: ");
- * Serial.println(current->getId());
- * current = current->getNext();
- * }
- * @endcode
- */
- __TASK_INLINE Task* getFirstTask() { return iFirst; };
- /**
- * @brief Returns a pointer to the last task in the scheduler's task chain
- *
- * This method provides direct access to the last task in the internal linked list
- * of tasks managed by this scheduler. It's useful for reverse iteration through
- * the task chain and for advanced task management operations.
- *
- * @return Pointer to the last task in the chain, or nullptr if no tasks are registered
- *
- * @note This method is only available when _TASK_EXPOSE_CHAIN compilation option is enabled.
- * @note The returned pointer should be treated as read-only to avoid corrupting the task chain.
- * @note Tasks are stored in a doubly-linked list internally.
- *
- * @warning Direct manipulation of the task chain can lead to undefined behavior.
- * Use the standard addTask() and deleteTask() methods instead.
- *
- * @see getFirstTask()
- * @see addTask()
- * @see deleteTask()
- * @see _TASK_EXPOSE_CHAIN
- *
- * Example usage:
- * @code
- * Scheduler ts;
- * Task t1, t2, t3;
- *
- * ts.addTask(t1);
- * ts.addTask(t2);
- * ts.addTask(t3);
- *
- * // Iterate through tasks in reverse order
- * Task* current = ts.getLastTask();
- * while (current != nullptr) {
- * Serial.print("Task ID (reverse): ");
- * Serial.println(current->getId());
- * current = current->getPrev();
- * }
- * @endcode
- */
- __TASK_INLINE Task* getLastTask() { return iLast; };
- #endif // _TASK_EXPOSE_CHAIN
- #ifdef _TASK_THREAD_SAFE
- /**
- * @brief Queues a task operation request for thread-safe execution
- *
- * This method places a pre-constructed request structure onto the task request queue
- * for later processing during the next scheduler execution cycle. This provides
- * thread-safe access to task operations from interrupt service routines or other
- * execution contexts.
- *
- * @param aRequest Pointer to a _task_request_t structure containing the operation details.
- * The structure should be properly initialized with the target object,
- * operation type, and parameters.
- *
- * @return true if the request was successfully queued, false if the queue is full
- *
- * @note This method is only available when _TASK_THREAD_SAFE compilation option is enabled.
- * @note The request structure must remain valid until the request is processed.
- * @note Requests are processed in FIFO order during scheduler execution.
- * @note The maximum number of queued requests is limited by the request queue size.
- *
- * @warning The aRequest pointer must point to a valid _task_request_t structure.
- * Invalid pointers will cause undefined behavior.
- *
- * @see requestAction(void*, _task_request_type_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
- * @see processRequests()
- * @see _task_request_t
- * @see _TASK_THREAD_SAFE
- *
- * Example usage:
- * @code
- * _task_request_t request;
- * request.object = &myTask;
- * request.type = TASK_REQUEST_ENABLE;
- * request.param1 = 0;
- * request.param2 = 0;
- * request.param3 = 0;
- * request.param4 = 0;
- * request.param5 = 0;
- *
- * if (ts.requestAction(&request)) {
- * Serial.println("Request queued successfully");
- * } else {
- * Serial.println("Request queue full");
- * }
- * @endcode
- */
- __TASK_INLINE bool requestAction(_task_request_t* aRequest);
- /**
- * @brief Queues a task operation request with individual parameters for thread-safe execution
- *
- * This method creates and queues a task operation request using individual parameters.
- * It provides a convenient interface for thread-safe task operations without requiring
- * manual construction of the request structure.
- *
- * @param aObject Pointer to the target object (Task or Scheduler) for the operation
- * @param aType Type of operation to perform (from _task_request_type_t enum)
- * @param aParam1 First parameter for the operation (interpretation depends on aType)
- * @param aParam2 Second parameter for the operation (interpretation depends on aType)
- * @param aParam3 Third parameter for the operation (interpretation depends on aType)
- * @param aParam4 Fourth parameter for the operation (interpretation depends on aType)
- * @param aParam5 Fifth parameter for the operation (interpretation depends on aType)
- *
- * @return true if the request was successfully queued, false if the queue is full
- *
- * @note This method is only available when _TASK_THREAD_SAFE compilation option is enabled.
- * @note Parameter interpretation varies by operation type - see _task_request_type_t documentation.
- * @note Unused parameters should be set to 0.
- * @note Requests are processed in FIFO order during scheduler execution.
- *
- * @warning The aObject pointer must point to a valid Task or Scheduler instance.
- * Invalid pointers will cause undefined behavior when the request is processed.
- *
- * @see requestAction(_task_request_t*)
- * @see processRequests()
- * @see _task_request_type_t
- * @see _TASK_THREAD_SAFE
- *
- * Example usage:
- * @code
- * // Request to enable a task from an ISR
- * void IRAM_ATTR sensorISR() {
- * ts.requestAction(&sensorTask, TASK_REQUEST_ENABLE, 0, 0, 0, 0, 0);
- * }
- *
- * // Request to restart a task with new interval
- * ts.requestAction(&myTask, TASK_REQUEST_RESTART, 5000, 0, 0, 0, 0); // 5 second interval
- *
- * // Request to set task iterations
- * ts.requestAction(&myTask, TASK_REQUEST_SET_ITERATIONS, 10, 0, 0, 0, 0); // 10 iterations
- * @endcode
- */
- __TASK_INLINE bool requestAction(void* aObject, _task_request_type_t aType, unsigned long aParam1, unsigned long aParam2, unsigned long aParam3, unsigned long aParam4, unsigned long aParam5);
- #endif
- _TASK_SCOPE:
- #ifdef _TASK_THREAD_SAFE
- __TASK_INLINE void processRequests();
- #endif
- Task *iFirst, *iLast, *iCurrent; // pointers to first, last and current tasks in the chain
- volatile bool iPaused, iEnabled;
- unsigned long iActiveTasks;
- unsigned long iTotalTasks;
- unsigned long iInvokedTasks;
- #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
- #ifdef _TASK_TICKLESS
- unsigned long iNextRun;
- #endif
- };
- #endif /* _TASKSCHEDULERDECLARATIONS_H_ */
|