userver: userver/engine/impl/future_state.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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