-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfuture.hpp
69 lines (58 loc) · 1.83 KB
/
future.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <deque>
#include <stdexcept>
#include <variant>
#include <TODO_qtils/variant_get.hpp>
#include "coro/handler.hpp"
#include "coro/set_thread.hpp"
namespace jam {
template <typename T>
class SharedFuture {
public:
using SelfSPtr = std::shared_ptr<SharedFuture<T>>;
SharedFuture(IoContextPtr io_context_ptr)
: io_context_ptr_{std::move(io_context_ptr)} {}
static Coro<bool> ready(SelfSPtr self) {
co_await setCoroThread(self->io_context_ptr_);
co_return std::holds_alternative<T>(self->state_);
}
/**
* Resumes coroutine immediately or inside `set`.
*/
static Coro<T> get(SelfSPtr self) {
co_await setCoroThread(self->io_context_ptr_);
if (auto value = qtils::variantGet<T>(self->state_)) {
co_return *value;
}
auto &handlers = std::get<Handlers>(self->state_);
co_return co_await coroHandler<T>([&](CoroHandler<T> &&handler) {
handlers.emplace_back(std::move(handler));
});
}
/**
* Set value and wake waiting coroutines.
* Coroutines may complete before `set` returns.
*/
static Coro<void> set(SelfSPtr self, T value) {
co_await setCoroThread(self->io_context_ptr_);
if (std::holds_alternative<T>(self->state_)) {
throw std::logic_error{"SharedFuture::set must be called once"};
}
auto handlers = std::move(std::get<Handlers>(self->state_));
self->state_ = std::move(value);
auto &state_value = std::get<T>(self->state_);
for (auto &handler : handlers) {
handler(state_value);
}
}
private:
using Handlers = std::deque<CoroHandler<T>>;
IoContextPtr io_context_ptr_;
std::variant<Handlers, T> state_;
};
} // namespace jam