Program Listing for File spawn.hpp

Return to documentation for file (include/concore/spawn.hpp)

#pragma once

#include "task.hpp"
#include "detail/exec_context_if.hpp"
#include "detail/library_data.hpp"

#include <initializer_list>

namespace concore {
inline namespace v1 {

inline void spawn(task&& t, bool wake_workers = true) {
    detail::do_spawn(detail::get_exec_context(), std::move(t), wake_workers);
}

template <typename F>
inline void spawn(F&& ftor, bool wake_workers = true) {
    auto grp = task_group::current_task_group();
    detail::do_spawn(detail::get_exec_context(), task(std::forward<F>(ftor), grp), wake_workers);
}

template <typename F>
inline void spawn(F&& ftor, task_group grp, bool wake_workers = true) {
    detail::do_spawn(
            detail::get_exec_context(), task(std::forward<F>(ftor), std::move(grp)), wake_workers);
}

inline void spawn(std::initializer_list<task_function>&& ftors, bool wake_workers = true) {
    auto grp = task_group::current_task_group();
    int count = static_cast<int>(ftors.size());
    for (const auto& ftor : ftors) {
        // wake_workers applies only to the last element; otherwise pass true
        bool cur_wake_workers = (count-- > 0 || wake_workers);
        detail::do_spawn(detail::get_exec_context(), task(ftor, grp), cur_wake_workers);
    }
}

inline void spawn(
        std::initializer_list<task_function>&& ftors, task_group grp, bool wake_workers = true) {
    int count = static_cast<int>(ftors.size());
    for (const auto& ftor : ftors) {
        // wake_workers applies only to the last element; otherwise pass true
        bool cur_wake_workers = (count-- > 0 || wake_workers);
        detail::do_spawn(detail::get_exec_context(), task(ftor, grp), cur_wake_workers);
    }
}

template <typename F>
inline void spawn_and_wait(F&& ftor) {
    auto& ctx = detail::get_exec_context();
    auto worker_data = detail::enter_worker(ctx);

    auto grp = task_group::create(task_group::current_task_group());
    detail::do_spawn(ctx, task(std::forward<F>(ftor), grp), false);
    detail::busy_wait_on(ctx, grp);

    detail::exit_worker(ctx, worker_data);
}

inline void spawn_and_wait(std::initializer_list<task_function>&& ftors, bool wake_workers = true) {
    auto& ctx = detail::get_exec_context();
    auto worker_data = detail::enter_worker(ctx);

    auto grp = task_group::create(task_group::current_task_group());
    int count = static_cast<int>(ftors.size());
    for (const auto& ftor : ftors) {
        bool cur_wake_workers = count-- > 0; // don't wake on the last task
        detail::do_spawn(ctx, task(ftor, grp), cur_wake_workers);
    }
    detail::busy_wait_on(ctx, grp);

    detail::exit_worker(ctx, worker_data);
}

inline void wait(task_group& grp) {
    auto& ctx = detail::get_exec_context();
    auto worker_data = detail::enter_worker(ctx);
    detail::busy_wait_on(ctx, grp);
    detail::exit_worker(ctx, worker_data);
}

struct spawn_executor {
    template <typename F>
    void execute(F&& f) const {
        do_spawn(detail::get_exec_context(), task{std::forward<F>(f)});
    }
    void execute(task t) { do_spawn(detail::get_exec_context(), std::move(t)); }

    friend inline bool operator==(spawn_executor, spawn_executor) { return true; }
    friend inline bool operator!=(spawn_executor, spawn_executor) { return false; }
};

struct spawn_continuation_executor {
    template <typename F>
    void execute(F&& f) const {
        do_spawn(detail::get_exec_context(), task{std::forward<F>(f)}, false);
    }
    void execute(task t) { do_spawn(detail::get_exec_context(), std::move(t), false); }

    friend inline bool operator==(spawn_continuation_executor, spawn_continuation_executor) {
        return true;
    }
    friend inline bool operator!=(spawn_continuation_executor, spawn_continuation_executor) {
        return false;
    }
};

} // namespace v1

} // namespace concore