Skip to content

Instantly share code, notes, and snippets.

@oliverepper
Last active November 19, 2022 10:10

Revisions

  1. oliverepper revised this gist Nov 19, 2022. 1 changed file with 13 additions and 5 deletions.
    18 changes: 13 additions & 5 deletions then_and_wait_on_lazy_future.cpp
    Original file line number Diff line number Diff line change
    @@ -6,21 +6,28 @@

    using namespace std;

    auto async_algo() {
    auto new_thread() {
    return [](auto p) {
    thread { [p=move(p)]() mutable {
    p.set_value(42);
    p.set_value();
    }}.detach();
    };
    }

    auto async_algo(auto task) {
    return then(task, []{
    return 42;
    });
    }

    template <typename T, typename N>
    struct then_sender {
    T p;
    N n;
    void set_value(auto ...args) {
    p.set_value(n(args...));
    }
    void set_exception(auto e) { p.set_exception(e); }
    };

    auto then(auto task, auto next) {
    @@ -69,11 +76,12 @@ T sync_wait(Task task) {


    int main() {
    auto f = async_algo();
    auto next = then(f, [](int i) {
    auto first = async_algo(new_thread());
    auto next = then(first, [](int i) {
    return i / 2;
    });

    printf("%d\n", sync_wait<int>(next));
    printf("%d\n", sync_wait<int>(next));

    return 0;
    }
  2. oliverepper revised this gist Nov 19, 2022. No changes.
  3. oliverepper revised this gist Nov 19, 2022. No changes.
  4. oliverepper revised this gist Nov 19, 2022. 1 changed file with 0 additions and 6 deletions.
    6 changes: 0 additions & 6 deletions then_and_wait_on_lazy_future.cpp
    Original file line number Diff line number Diff line change
    @@ -14,12 +14,6 @@ auto async_algo() {
    };
    }

    struct sink {
    void set_value(auto arg) {
    cout << "Received value in sink: " << arg << endl;
    }
    };

    template <typename T, typename N>
    struct then_sender {
    T p;
  5. oliverepper created this gist Nov 19, 2022.
    85 changes: 85 additions & 0 deletions then_and_wait_on_lazy_future.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    /*
    * This is all Eric Nieblers work, see: https://youtu.be/h-ExnuD6jms
    */
    #include <iostream>
    #include <thread>

    using namespace std;

    auto async_algo() {
    return [](auto p) {
    thread { [p=move(p)]() mutable {
    p.set_value(42);
    }}.detach();
    };
    }

    struct sink {
    void set_value(auto arg) {
    cout << "Received value in sink: " << arg << endl;
    }
    };

    template <typename T, typename N>
    struct then_sender {
    T p;
    N n;
    void set_value(auto ...args) {
    p.set_value(n(args...));
    }
    };

    auto then(auto task, auto next) {
    return [=](auto p) {
    task(then_sender<decltype (p), decltype (next)>{p, next});
    };
    }

    template <typename T>
    struct _state {
    mutex mtx;
    condition_variable cv;
    variant<monostate, exception_ptr, T> data;
    };

    template <typename T>
    struct _promise {
    _state<T>* pst;

    template<int I> void _set(auto... xs) {
    auto lk = unique_lock{pst->mtx};
    pst->data.template emplace<I>(xs...);
    pst->cv.notify_one();
    }
    void set_value(auto... vs) { _set<2>(vs...); }
    void set_exception(auto e) { _set<1>(e); }
    };

    template <typename T, typename Task>
    T sync_wait(Task task) {
    _state<T> state;
    task(_promise<T>{&state});

    {
    auto lk = unique_lock{state.mtx};
    state.cv.wait(lk, [&state] {
    return state.data.index() != 0;
    });
    }

    if (state.data.index() == 1)
    rethrow_exception(get<1>(state.data));

    return move(get<2>(state.data));
    };


    int main() {
    auto f = async_algo();
    auto next = then(f, [](int i) {
    return i / 2;
    });

    printf("%d\n", sync_wait<int>(next));
    return 0;
    }