taskorch
System Composition
The entire concurrency library can generally be divided into four main components:
- Task — The minimal unit of execution, built from a fn or closure along with runtime metadata.
- Queue — The queue holds tasks that are waiting to be processed. It acts as a buffer where tasks are stored until they can be executed.
- Threads — Threads are responsible for executing the tasks retrieved from the queue.
- Resource Pool — Responsible for the lifecycle management of both the Queue and the Threads, establishing a mapping between names and instances.
Task
Task Modes
Tasks can be executed in two distinct modes:
- Independent: Runs freely without constraint.
- Conditional: Executes only when all conditions are satisfied.
Task Flow
- Activation:
A task is scheduled once all its required conditions are fulfilled. - Execution:
The task runs and computes its return value. - Data Passing:
If atarget anchoris configured, the return value will be passed on to another task.
Key Notes:
- Conditions correspond to the function’s parameters (0-indexed).
Task ID Assignment
- Explicit ID: You can provide your own ID using a generator or by calling
taskid_next(). - Auto-generated: If you omit specifying an ID, the system will automatically assign one.
Building a Task (3-Step Process)
- Prepare: Define a function or closure.
- Create: Create the task chained by
.into_task(). - Notify (Optional): Chain tasks by calling
to()to set atarget anchor.
This step can be skipped if the task does not produce any output.
Usage
Add only one of the following lines to your Cargo.toml:
# No logs, no color
= "0.2.1"
# With logging, and colored output
= {="0.2.1", =["log-info", "log-color"]}
Optional features can be enabled based on your needs (see Available Features).
Task Creation Code
Note
NO parameter, NO taskid needed.
NO return, NO target anchor required.
Case 1: [ No parameter, No return ]
# use TaskBuildNew as _;
let task =
// <1> Define the body
.into_task; // <2> Create a task from the given closure.
// <3> `to()` skipped, as there is no return value
Case 2: [ No parameter, With return ]
# use ;
let task =
// <1> Define the body
.into_task // <2> Create a task from the given closure.
.to; // <3> Set target;
// the return value will be forwarded to task #2, condition #0.
let task =
// <1> ..
.into_task; // <2> ..
// <3> `to()` skipped, the return value dropped
Case 3: [ With parameter, No return ]
# use TaskBuildNew as _;
let task =
// <1> Define the body, taskid is auto-generated.
.into_task; // <2> Create a task from the given closure.
// <3> `to()` skipped, as there is no return value
let task =
// <1> Define the body, with an explicit taskid.
.into_task; // <2> ..
// <3> ..
Case 4: [ With parameter, With return ]
# use ;
let task =
// <1> Define the body, taskid is auto-generated.
.into_task; // <2> Create a task from the given closure.
// <3> `to()` skipped, the return value dropped
let task =
// <1> Define the body, with an explicit taskid.
.into_task; // <2> ..
// <3> ..
let task =
// <1> Define the body, taskid is auto-generated.
.into_task // <2> Create a task from the given closure.
.to; // <3> Set target;
// the return value will be forwarded to task #2 and cond #0
let task =
// <1> Define the body, with an explicit taskid.
.into_task // <2> ..
.to; // <3> ..
Exit task creation
The only difference here is the use of .into_exit_task() instead of .into_task().
⚠️ Type cast NOTE
❗ Error-prone operation!
When forwarding a task result to a conditional task's condition point:
- Ensure the result type must be identical to the condition type.
- Violation will trigger
panic!
# use ;
// Sample code explanation
let cc = ; // the type of cond #0 is `i32`
// the type of cond #1 is `i8`
let f0 = ; // the return type is `i32`
let f1 = ; // the return type is `i8`
let task_cc = .into_task; // taskid is explicitly set to 1
let task_f0 = f0.into_task.to; // *** return type `i32` === cond #0 type `i32` ***
let task_f1 = f1.into_task.to; // *** return type `i8` === cond #1 type `i8` ***
⚠️ API NOTE
As this project is currently in early active development, the API is highly unstable and will change in subsequent versions.
Example
use ;
// create 3 tasks and run
For a more complex demo, see the usage and spsc example.
cargo run --example usage --features="log-trace,log-color"
cargo run --example spsc --features="log-trace,log-color"
Available Features
All logs are compile-time controlled and have zero runtime overhead when disabled.
log-error: Logs ERROR level onlylog-warn: Logs WARN level and abovelog-info: Logs INFO level and abovelog-debug: Logs DEBUG level and abovelog-trace: Logs TRACE level and above (most verbose)log-color: Adds ANSI color to log messages in the terminal
⚠️ Note:
These features are mutually exclusive - only one or none can be enabled at a time.
No logs are emitted by default.
Color is disabled by default.
🕒 Timestamp Format in Logs
The timestamp used in logs is measured from the earliest of the following events:
- The time when the first log message was emitted
- The time when the first
Poolwas created
This is a relative time (not absolute wall-clock time), designed for analyzing task sequences.