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 engine::impl::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 class WaitStrategy;
30
31 FutureStateBase() noexcept;
32 ~FutureStateBase();
33
34 void LockResultStore();
35 void ReleaseResultStore();
36 void WaitForResult();
37
38 private:
39 void AppendWaiter(impl::TaskContext& context) noexcept final;
40 void RemoveWaiter(impl::TaskContext& context) noexcept final;
41
42 FastPimplWaitListLight finish_waiters_;
43 std::atomic<bool> is_ready_;
44 std::atomic<bool> is_result_store_locked_;
45 std::atomic<bool> is_future_created_;
46};
47
48template <typename T>
49class FutureState final : public FutureStateBase {
50 public:
51 [[nodiscard]] T Get();
52
53 void SetValue(const T& value);
54 void SetValue(T&& value);
55 void SetException(std::exception_ptr&& ex);
56
57 private:
58 void RethrowErrorResult() const override;
59
60 utils::ResultStore<T> result_store_;
61};
62
63template <>
64class FutureState<void> final : public FutureStateBase {
65 public:
66 void Get();
67
68 void SetValue();
69 void SetException(std::exception_ptr&& ex);
70
71 private:
72 void RethrowErrorResult() const override;
73
74 utils::ResultStore<void> result_store_;
75};
76
77template <typename T>
78T FutureState<T>::Get() {
79 WaitForResult();
80 return result_store_.Retrieve();
81}
82
83template <typename T>
84void FutureState<T>::SetValue(const T& value) {
85 LockResultStore();
86 result_store_.SetValue(value);
87 ReleaseResultStore();
88}
89
90template <typename T>
91void FutureState<T>::SetValue(T&& value) {
92 LockResultStore();
93 result_store_.SetValue(std::move(value));
94 ReleaseResultStore();
95}
96
97template <typename T>
98void FutureState<T>::SetException(std::exception_ptr&& ex) {
99 LockResultStore();
100 result_store_.SetException(std::move(ex));
101 ReleaseResultStore();
102}
103
104template <typename T>
105void FutureState<T>::RethrowErrorResult() const {
106 (void)result_store_.Get();
107}
108
109inline void FutureState<void>::Get() {
110 WaitForResult();
111 return result_store_.Retrieve();
112}
113
114inline void FutureState<void>::SetValue() {
115 LockResultStore();
116 result_store_.SetValue();
117 ReleaseResultStore();
118}
119
120inline void FutureState<void>::SetException(std::exception_ptr&& ex) {
121 LockResultStore();
122 result_store_.SetException(std::move(ex));
123 ReleaseResultStore();
124}
125
126inline void FutureState<void>::RethrowErrorResult() const {
127 (void)result_store_.Get();
128}
129
130} // namespace engine::impl
131
132USERVER_NAMESPACE_END