taskorch 0.1.0

Concurrent Pool for task processing
Documentation
  • Coverage
  • 80%
    28 out of 35 items documented1 out of 16 items with examples
  • Size
  • Source code size: 49.07 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 5.03 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 21s Average build duration of successful builds.
  • all releases: 15s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hailongxu/taskorch
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hailongxu

Task Orch

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

  1. Activation:
    A task is scheduled once all its required conditions are fulfilled.
  2. Execution:
    The task runs and computes its return value.
  3. Data Passing:
    If a target anchor is 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)

  1. Prepare: Define a function or closure.
  2. Create: Create the task chained by .task().
  3. Notify (Optional): Chain tasks by calling to() to set a target anchor.
    This step can be skipped if the task does not produce any output.

Task Creation Code

Note

NO parameter, NO taskid needed.
NO return, NO target anchor required.

Case 1: [ No parameter, No return ]

# use taskorch::TaskBuildNew as _;
let task = 
    (||{})          // <1> Define the body
        .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 taskorch::{TaskBuildNew as _, TaskBuildOp as _};
let task = 
    (||{3})         // <1> Define the body
        .task()     // <2> Create a task from the given closure.
        .to(2,0);   // <3> Set target;
                    //     the return value will be forwarded to task #2, condition #0.

let task = 
    (||{3})         // <1> ..
        .task();    // <2> ..
                    // <3> `to()` skipped, the return value dropped

Case 3: [ With parameter, No return ]

# use taskorch::TaskBuildNew as _;

let task = 
    (|_:i8|{})      // <1> Define the body, taskid is auto-generated.
        .task();    // <2> Create a task from the given closure.
                    // <3> `to()` skipped, as there is no return value
let task = 
    (|_:i8|{}, 1)   // <1> Define the body, with an explicit taskid.
        .task();    // <2> ..
                    // <3> ..

Case 4: [ With parameter, With return ]

# use taskorch::{TaskBuildNew as _, TaskBuildOp as _};

let task = 
    (|_:i8|{3})     // <1> Define the body, taskid is auto-generated.
        .task();    // <2> Create a task from the given closure.
                    // <3> `to()` skipped, the return value dropped
let task = 
    (|_:i8|{3}, 1)  // <1> Define the body, with an explicit taskid.
        .task();    // <2> ..
                    // <3> ..

let task = 
    (|_:i8|{3})     // <1> Define the body, taskid is auto-generated.
        .task()     // <2> Create a task from the given closure.
        .to(2,0);   // <3> Set target;
                    //     the return value will be forwarded to task #2 and cond #0

let task = 
    (|_:i8|{3}, 1) // <1> Define the body, with an explicit taskid.
        .task()    // <2> ..
        .to(2,0);  // <3> ..

Exit task creation
The only difference here is the use of .exit_task() instead of .task().

Note

As this is the initial development release (v0.1.0), the API is highly unstable and will change in subsequent versions.

Example

use taskorch::{Pool, Queue, TaskBuildNew, TaskBuildOp};

fn main() {
    println!("----- test task orch -----");

    // Step#1. create a Pool
    let mut pool = Pool::new();

    // Step#2. create a queue
    let qid = pool.insert_queue(&Queue::new()).unwrap();
    let submitter = pool.task_submitter(qid).unwrap();

    // Step#3. create tasks

    // an indepent task
    submitter.submit((||println!("task free say hello")).task());

    // an exit task with ONE str cond
    let id_exit = submitter.submit(
        (
            |msg:&str|println!("exit task, recved ({msg:?}) and EXIT"),
            1

        ).exit_task()
    );
    assert_eq!(id_exit,1);

    // normal task pass message to exit task
    submitter.submit(
        (move||{
            let id_exit = &id_exit;
            println!("normal pass [\"msg:exit\"] to: task#{id_exit}");
            "msg:exit"
        }).task().to(id_exit, 0)
    );

    // Step#4. start a thread and run
    pool.spawn_thread_for(qid);

    // Step#5. wait until all finished
    pool.join();
}

For a more complex demo, see the usage example.