Skip to content

Instantly share code, notes, and snippets.

@djg
Created March 3, 2020 03:09
Show Gist options
  • Select an option

  • Save djg/81f3797b4e291feb63cd26c6ab4c3055 to your computer and use it in GitHub Desktop.

Select an option

Save djg/81f3797b4e291feb63cd26c6ab4c3055 to your computer and use it in GitHub Desktop.

Revisions

  1. djg created this gist Mar 3, 2020.
    74 changes: 74 additions & 0 deletions task_system.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    /* Horrible task system */
    #include <condition_variable>
    #include <deque>
    #include <functional>
    #include <mutex>
    #include <thread>
    #include <vector>

    using namespace std;

    using lock_t = unique_lock<mutex>;

    class notification_queue {
    deque<function<void()>> _q;
    mutex _mutex;
    condition_variable _ready;
    bool _done{false};

    public:
    void done() {
    {
    unique_lock<mutex> lock{_mutex};
    _done = true;
    }
    }

    bool pop(function<void()>& x) {
    lock_t lock{_mutex};
    while (_q.empty() && !_done) _ready.wait(lock);
    if (_q.empty()) return false;
    x = move(_q.front());
    _q.pop_front();
    return true;
    }

    template<typename F>
    void push(F&& f) {
    {
    lock_t lock{_mutex};
    _q.emplace_back(forward<F>(f));
    }
    _ready.notify_one();
    }
    };

    class task_system {
    const unsigned _count{thread::hardware_concurrency()};
    vector<thread> _threads;
    notification_queue _q;

    void run(unsigned i) {
    while (true) {
    function<void()> f;
    _q.pop(f);
    f();
    }
    }

    public:
    task_system() {
    for (unsigned n = 0; n != _count; ++n) {
    _threads.emplace_back([&, n]{ run(n); });
    }
    }

    ~task_system() {
    for (auto& e : _threads) e.join();
    }

    template <typename F>
    void async_(F&& f) {
    _q.push(forward<F>(f));
    }
    };