Skip to content

Instantly share code, notes, and snippets.

@oliverepper
Last active November 19, 2022 10:10
Show Gist options
  • Save oliverepper/f711b8548d8aa9c82fa590663db298a3 to your computer and use it in GitHub Desktop.
Save oliverepper/f711b8548d8aa9c82fa590663db298a3 to your computer and use it in GitHub Desktop.
/*
* This is all Eric Nieblers work, see: https://youtu.be/h-ExnuD6jms
*/
#include <iostream>
#include <thread>
using namespace std;
auto new_thread() {
return [](auto p) {
thread { [p=move(p)]() mutable {
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) {
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 first = async_algo(new_thread());
auto next = then(first, [](int i) {
return i / 2;
});
printf("%d\n", sync_wait<int>(next));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment