Skip to content
Amanieu edited this page Mar 24, 2013 · 16 revisions

NOTE: Work in progress

task

class task<Result> {
    // Result type of the task
    typedef Result result_type;

    // Create an empty task object (operator bool returns false)
    task();

    // Movable but not copyable
    task(const task&) = delete;
    task(task&&);
    task& operator=(const task&) = delete;
    task& operator=(task&&);

    // Destroys the task object. Does not wait for the task to finish.
    ~task();

    // Returns true if this task object contains a reference to a valid task.
    // If this is not the case then all other functions throw std::invalid_argument.
    explicit operator bool() const;

    // Waits for the task to complete and then retrieves the result of the task.
    // If the task contains an exception then that exception is rethrown. The
    // result is moved out of the task, and then the task is cleared (operator
    // bool returns false).
    Result get();

    // Waits for the task to have finished executing
    void wait() const;

    // Returns whether the task has finished executing
    bool ready() const;

    //
    task<T> then(Func f); // T = result type of f
    task<T> then(scheduler& sched, Func f); // T = result type of f

    //
    shared_task<Result> share();
};

class shared_task<Result> {
    typedef Result result_type;
    shared_task();
    shared_task(const shared_task&);
    shared_task(shared_task&&);
    shared_task& operator=(const shared_task&);
    shared_task& operator=(shared_task&&);
    ~shared_task();
    explicit operator bool() const;
    void get() const; // If Result is void
    Result& get() const; // If Result is a reference type
    const Result& get() const; // Otherwise
    void wait() const;
    bool ready() const;
    task<T> then(Func f) const; // T = result type of f
    task<T> then(scheduler& sched, Func f) const; // T = result type of f
};

// Create a task already containing the given value
task<T> make_task(T value);
task<void> make_task();

// Spawn a task to run the given function, optionally using the given scheduler
// instead of the default. The default scheduler can be overriden by defining
// the LIBASYNC_DEFAULT_SCHEDULER preprocessor macro.
task<T> spawn(Func f); // T = result type of f
task<T> spawn(scheduler& sched, Func f); // T = result type of f

local_task

class local_task<Func> {
    // Local tasks can only be created using local_spawn()
    local_task() = delete;

    // Local tasks are non-movable and non-copyable
    local_task(const local_task&) = delete;
    local_task(local_task&&) = delete;
    local_task& operator=(const local_task&) = delete;
    local_task& operator=(local_task&&) = delete;

    // The destructor implicitly waits for the task to finish
    ~local_task();

    // Waits for the task to complete and then retrieves the result of the task.
    // If the task contains an exception then that exception is rethrown. The
    // result is moved out of the task.
    void get(); // If Result == void
    Result& get(); // If Result is a reference type
    Result get(); // Otherwise

    // Waits for the task to have finished executing
    void wait() const;

    // Returns whether the task has finished executing
    bool ready() const;
};

// Spawn a local task to run the given function, optionally using the given
// scheduler instead of the default. The default scheduler can be overriden by
// defining the LIBASYNC_DEFAULT_SCHEDULER preprocessor macro.
local_task<Func> local_spawn(Func f);
local_task<Func> local_spawn(scheduler& sched, Func f);

event_task

class event_task<Result> {
    event_task();
    event_task(const event_task&) = delete;
    event_task(event_task&&);
    event_task& operator=(const event_task&) = delete;
    event_task& operator=(event_task&&);
    ~event_task();
    task<Result> get_task() const;
    bool set() const; // If Result == void
    bool set(Result& r) const; // If Result is a reference type
    bool set(Result&& r) const; // Otherwise
    bool set(const Result& r) const; // Otherwise
    bool set_exception(std::exception_ptr except) const;
    bool cancel() const;
};

when_all/when_any

// For T = void, return value is task<size_t>
task<std::pair<size_t, T>> when_any(task<T>/shared_task<T>... tasks); // All T must be the same
task<std::pair<size_t, T>> when_any(Iter begin, Iter end); // Range of task<T> or shared_task<T>
task<std::pair<size_t, T>> when_any(Range tasks); // Range of task<T> or shared_task<T>

struct void_ {};
task<std::tuple<T...>> when_all(task<T>/shared_task<T>... tasks); // Allows different T types, void becomes void_

// For T = void, return value is task<void>
task<std::vector<T>> when_all(Iter begin, Iter end); // Range of task<T> or shared_task<T>
task<std::vector<T>> when_all(Range tasks); // Range of task<T> or shared_task<T>

Cancellation

// Exception thrown by cancel_current_task
struct task_canceled {};

// A cancellation token is a boolean flag which indicates a cancellation request
class cancellation_token {
    // A token is initialized to the 'not canceled' state
    cancellation_token();

    // Tokens are non-movable and non-copyable
    cancellation_token(const cancellation_token&) = delete;
    cancellation_token(cancellation_token&&) = delete;
    cancellation_token& operator=(const cancellation_token&) = delete;
    cancellation_token& operator=(cancellation_token&&) = delete;

    // Returns whether the token has been canceled
    bool is_canceled() const;

    // Sets the token to the canceled state
    void cancel();
};

// Throws a task_canceled exception
void cancel_current_task();

// Calls cancel_current_task() if the token is canceled
void interruption_point(const cancellation_token& token);

Task scheduling

class task_handle {
    // Create a null task handle which does not contain a valid task
    task_handle();

    // Task handles are movable but not copyable
    task_handle(const task_handle&) = delete;
    task_handle(task_handle&&);
    task_handle& operator=(const task_handle&) = delete;
    task_handle& operator=(task_handle&&);

    // Checks whether the task handle is valid
    explicit operator bool() const;

    // Executes the task and invalidates the handle
    void run();

    // Convert to and from void pointer
    void* to_void_ptr();
    static task_handle from_void_ptr(void*);
};

class scheduler {
    virtual void schedule(task_handle t) = 0;
};

scheduler& default_scheduler();
scheduler& inline_scheduler();
scheduler& thread_scheduler();
Clone this wiki locally