1/// @brief Complex task with dependencies, scheduling, and resource management
3/// @defgroup complextask ComplexTask
7/// ComplexTask extends Task with advanced features:
8/// - **Dependencies** - Wait for other tasks to complete before running
9/// - **Resource requirements** - Acquire exclusive access to shared resources (mutexes, FIFO queues, gates)
10/// - **Scheduling** - Run at specific times or after delays
11/// - **Deferment** - Hold tasks indefinitely until explicitly advanced
12/// - **Soft failures** - Continue running even if dependencies fail
13/// - **Cascading cancellation** - Optionally cancel dependencies when cancelled
15/// ComplexTask can only run on a ComplexTaskQueue (the default queue type). The queue
16/// maintains separate lists for scheduled and deferred tasks, and manages resource acquisition.
18#include <cx/thread/rwlock.h>
19#include <cx/taskqueue/requires/taskrequires.cxh>
20#include <cx/taskqueue/resource/taskresource.cxh>
22/// ctaskDependOn(ComplexTask *task, Task *dep)
24/// Make task depend on another task completing successfully.
25/// If dep fails, task will fail without running.
26#define ctaskDependOn(task, dep) ctaskRequireTask(task, dep, false)
28/// ctaskWaitFor(ComplexTask *task, Task *dep)
30/// Make task wait for another task to complete, but don't fail if dep fails.
31#define ctaskWaitFor(task, dep) ctaskRequireTask(task, dep, true)
33/// ctaskDependOnTimeout(ComplexTask *task, Task *dep, int64 timeout)
35/// Make task depend on another task with a timeout.
36#define ctaskDependOnTimeout(task, dep, timeout) ctaskRequireTaskTimeout(task, dep, false, timeout)
38/// ctaskWaitForTimeout(ComplexTask *task, Task *dep, int64 timeout)
40/// Make task wait for another task with a timeout.
41#define ctaskWaitForTimeout(task, dep, timeout) ctaskRequireTaskTimeout(task, dep, true, timeout)
45/// Return values from ComplexTask::run() extending BasicTaskRunResultEnum
46enum ComplexTaskRunResultEnum {
47 TASK_Result_Schedule = TASK_Result_Basic_Count, ///< Reschedule task to run after delay specified in TaskControl.delay
48 TASK_Result_Schedule_Progress, ///< Same as Schedule, but marks progress (prevents stall warnings)
49 TASK_Result_Defer, ///< Defer task until manually advanced
50 TASK_Result_Defer_Progress, ///< Same as Defer, but marks progress
51 TASK_Result_Complex_Count
54/// Flags controlling ComplexTask behavior
55enum ComplexTaskFlagsEnum {
56 TASK_Cancel_Cascade = 0x01, ///< Cancel dependencies when this task is cancelled
57 TASK_Retain_Requires = 0x02, ///< Keep acquired resources across schedule/defer cycles
58 TASK_Soft_Requires = 0x04, ///< Allow task to run even if some dependencies fail
59 TASK_Cancel_Expired = 0x08, ///< Cancel dependencies that exceed their timeout
60 TASK_Require_Failed = 0xa0, ///< [Internal] Set when a soft requirement failed
63/// Internal flags reserved for scheduler use
64enum ComplexTaskInternalFlagsEnum {
65 TASK_INTERNAL_Owns_Resources = 0x01, ///< The task has acquired resources and needs to release them
68class ComplexTaskQueue;
70/// Complex task with dependencies, scheduling, and resource management.
71[methodprefix ctask] abstract class ComplexTask extends Task implements Sortable implements Hashable {
72 int64 nextrun; ///< Next scheduled run time
73 int64 lastprogress; ///< Timestamp of last progress change
74 weak:ComplexTaskQueue lastq; ///< Last queue this task ran on before being deferred
75 [noinit] sarray:object:TaskRequires _requires; ///< List of requirements (dependencies, resources, gates)
76 uint16 flags; ///< Task behavior flags (ComplexTaskFlagsEnum)
77 uint16 _intflags; ///< Internal flags reserved for scheduler use
78 atomic:uint32 _advcount; ///< Number of times task has been advanced
80 /// Add a task dependency.
81 /// @param dep Task to depend on
82 /// @param failok If true, don't fail if dep fails (soft dependency)
83 unbound void requireTask([in] Task *dep, bool failok);
84 /// Add a task dependency with timeout.
85 /// @param dep Task to depend on
86 /// @param failok If true, don't fail if dep fails
87 /// @param timeout Maximum time to wait for dep
88 unbound void requireTaskTimeout([in] Task *dep, bool failok, int64 timeout);
89 /// Add a resource requirement.
90 /// @param res Resource to acquire exclusively
91 unbound void requireResource([in] TaskResource *res);
92 /// Add a resource requirement with timeout.
93 /// @param res Resource to acquire
94 /// @param timeout Maximum time to wait for resource
95 unbound void requireResourceTimeout([in] TaskResource *res, int64 timeout);
96 /// Add a gate requirement.
97 /// @param gate Gate that must be opened before task runs
98 unbound void requireGate([in] TRGate *gate);
99 /// Add a gate requirement with timeout.
100 /// @param gate Gate to wait for
101 /// @param timeout Maximum time to wait for gate
102 unbound void requireGateTimeout([in] TRGate *gate, int64 timeout);
103 /// Add a generic requirement.
104 /// @param req Custom requirement object
105 unbound void require([in] TaskRequires *req);
107 /// Advance a deferred task to run as soon as possible.
108 /// @return true if task was advanced
109 unbound bool advance();
110 /// Check if all requirements are satisfied.
111 /// @param updateProgress If true, update lastprogress timestamp
112 /// @param expires [out] Earliest expiration time of any requirement
113 /// @return Requirement state (TASK_Requires_Wait, TASK_Requires_Ok, etc.)
114 unbound uint32 checkRequires(bool updateProgress, [out] [opt] int64 *expires);
115 /// Cascade cancellation to dependencies if TASK_Cancel_Cascade is set.
116 unbound void cancelRequires();
117 /// Try to acquire required resources.
118 /// @param acquired [out] List of successfully acquired resources
119 /// @return true if all resources were acquired
120 unbound bool acquireRequires(sa_TaskRequires *acquired);
121 /// Release previously acquired resources.
122 /// @param resources List of resources to release
123 /// @return true if resources were released
124 unbound bool releaseRequires(sa_TaskRequires resources);
125 /// Callback for use in closures to advance task.
126 /// @param cvars Captured variables (weak reference to task)
127 /// @param args Closure arguments
128 /// @return true if task was advanced
129 standalone bool advanceCallback(stvlist *cvars, stvlist *args);