userver: userver/utils/result_store.hpp Source File
Loading...
Searching...
No Matches
result_store.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/result_store.hpp
4/// @brief @copybrief utils::ResultStore
5
6#include <exception>
7#include <optional>
8#include <stdexcept>
9#include <utility>
10
11USERVER_NAMESPACE_BEGIN
12
13namespace utils {
14
15/// @ingroup userver_universal userver_containers
16///
17/// Simple value/exception store
18template <typename T>
19class ResultStore final {
20public:
21 /// @brief Retrieves the stored value or rethrows the stored exception
22 /// @throws std::logic_error if no value/exception stored
23 /// @note Can be called at most once.
25
26 /// @brief Returns the stored value or rethrows the stored exception
27 /// @throws std::logic_error if no value/exception stored
28 const T& Get() const&;
29
30 /// Stores a value
31 void SetValue(const T&);
32
33 /// Stores a value
34 void SetValue(T&&);
35
36 /// Stores an exception
37 void SetException(std::exception_ptr&&) noexcept;
38
39 // Returns the stored exception if present
40 std::exception_ptr GetException() const noexcept;
41
42private:
43 // variant here would require a specialization for exception_ptr
44 std::optional<T> value_;
45 std::exception_ptr exception_;
46};
47
48/// @ingroup userver_universal userver_containers
49///
50/// Simple void value/exception store
51template <>
52class ResultStore<void> final {
53public:
54 /// @brief Checks value availability or rethrows the stored exception
55 /// @throws std::logic_error if no value/exception stored
56 void Retrieve();
57
58 void Get() const&;
59
60 /// Marks the value as available
61 void SetValue() noexcept;
62
63 /// Stores an exception
64 void SetException(std::exception_ptr&&) noexcept;
65
66 // Returns the stored exception if present
67 std::exception_ptr GetException() const noexcept;
68
69private:
70 bool has_value_{false};
71 std::exception_ptr exception_;
72};
73
74template <typename T>
75T ResultStore<T>::Retrieve() {
76 if (value_) {
77 return std::move(*value_);
78 }
79 if (exception_) {
80 std::rethrow_exception(exception_);
81 }
82 throw std::logic_error("result store is not ready");
83}
84
85template <typename T>
86const T& ResultStore<T>::Get() const& {
87 if (value_) {
88 return *value_;
89 }
90 if (exception_) {
91 std::rethrow_exception(exception_);
92 }
93 throw std::logic_error("result store is not ready");
94}
95
96template <typename T>
97void ResultStore<T>::SetValue(const T& value) {
98 value_ = value;
99}
100
101template <typename T>
102void ResultStore<T>::SetValue(T&& value) {
103 value_.emplace(std::move(value));
104}
105
106template <typename T>
107void ResultStore<T>::SetException(std::exception_ptr&& exception) noexcept {
108 exception_ = std::move(exception);
109}
110
111template <typename T>
112std::exception_ptr ResultStore<T>::GetException() const noexcept {
113 return exception_;
114}
115
116// NOLINTNEXTLINE(readability-make-member-function-const)
117inline void ResultStore<void>::Retrieve() { Get(); }
118
119inline void ResultStore<void>::Get() const& {
120 if (has_value_) {
121 return;
122 }
123 if (exception_) {
124 std::rethrow_exception(exception_);
125 }
126 throw std::logic_error("result store is not ready");
127}
128
129inline void ResultStore<void>::SetValue() noexcept { has_value_ = true; }
130
131inline void ResultStore<void>::SetException(std::exception_ptr&& exception) noexcept {
132 exception_ = std::move(exception);
133}
134
135inline std::exception_ptr ResultStore<void>::GetException() const noexcept { return exception_; }
136
137} // namespace utils
138
139USERVER_NAMESPACE_END