userver: userver/engine/impl/future_state.hpp Source File
Loading...
Searching...
No Matches
future_state.hpp
1#pragma once
2
3#include <atomic>
4#include <exception>
5
6#include <userver/engine/deadline.hpp>
7#include <userver/engine/future_status.hpp>
8#include <userver/engine/impl/context_accessor.hpp>
9#include <userver/engine/impl/wait_list_fwd.hpp>
10#include <userver/utils/result_store.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace engine::impl {
15
16class FutureStateBase : private ContextAccessor {
17 public:
18 bool IsReady() const noexcept final;
19
20 [[nodiscard]] FutureStatus WaitUntil(Deadline deadline);
21
22 void OnFutureCreated();
23 bool IsFutureCreated() const noexcept;
24
25 // Internal helper for WaitAny/WaitAll
26 ContextAccessor* TryGetContextAccessor() noexcept { return this; }
27
28 protected:
29 FutureStateBase() noexcept;
30 ~FutureStateBase();
31
32 void LockResultStore();
33 void ReleaseResultStore();
34 void WaitForResult();
35
36 private:
37 friend class FutureWaitStrategy<FutureStateBase>;
38
39 EarlyWakeup TryAppendWaiter(TaskContext& waiter) final;
40 void RemoveWaiter(TaskContext& waiter) noexcept final;
41 void AfterWait() noexcept final;
42
43 FastPimplWaitListLight finish_waiters_;
44 std::atomic<bool> is_ready_;
45 std::atomic<bool> is_result_store_locked_;
46 std::atomic<bool> is_future_created_;
47};
48
49template <typename T>
50class FutureState final : public FutureStateBase {
51 public:
52 [[nodiscard]] T Get();
53
54 void SetValue(const T& value);
55 void SetValue(T&& value);
56 void SetException(std::exception_ptr&& ex);
57
58 private:
59 void RethrowErrorResult() const override;
60
61 utils::ResultStore<T> result_store_;
62};
63
64template <>
65class FutureState<void> final : public FutureStateBase {
66 public:
67 void Get();
68
69 void SetValue();
70 void SetException(std::exception_ptr&& ex);
71
72 private:
73 void RethrowErrorResult() const override;
74
75 utils::ResultStore<void> result_store_;
76};
77
78template <typename T>
79T FutureState<T>::Get() {
80 WaitForResult();
81 return result_store_.Retrieve();
82}
83
84template <typename T>
85void FutureState<T>::SetValue(const T& value) {
86 LockResultStore();
87 result_store_.SetValue(value);
88 ReleaseResultStore();
89}
90
91template <typename T>
92void FutureState<T>::SetValue(T&& value) {
93 LockResultStore();
94 result_store_.SetValue(std::move(value));
95 ReleaseResultStore();
96}
97
98template <typename T>
99void FutureState<T>::SetException(std::exception_ptr&& ex) {
100 LockResultStore();
101 result_store_.SetException(std::move(ex));
102 ReleaseResultStore();
103}
104
105template <typename T>
106void FutureState<T>::RethrowErrorResult() const {
107 (void)result_store_.Get();
108}
109
110inline void FutureState<void>::Get() {
111 WaitForResult();
112 return result_store_.Retrieve();
113}
114
115inline void FutureState<void>::SetValue() {
116 LockResultStore();
117 result_store_.SetValue();
118 ReleaseResultStore();
119}
120
121inline void FutureState<void>::SetException(std::exception_ptr&& ex) {
122 LockResultStore();
123 result_store_.SetException(std::move(ex));
124 ReleaseResultStore();
125}
126
127inline void FutureState<void>::RethrowErrorResult() const {
128 (void)result_store_.Get();
129}
130
131} // namespace engine::impl
132
133USERVER_NAMESPACE_END