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.
24 T Retrieve();
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
39private:
40 // variant here would require a specialization for exception_ptr
41 std::optional<T> value_;
42 std::exception_ptr exception_;
43};
44
45/// @ingroup userver_universal userver_containers
46///
47/// Simple void value/exception store
48template <>
49class ResultStore<void> final {
50public:
51 /// @brief Checks value availability or rethrows the stored exception
52 /// @throws std::logic_error if no value/exception stored
53 void Retrieve();
54
55 void Get() const&;
56
57 /// Marks the value as available
58 void SetValue() noexcept;
59
60 /// Stores an exception
61 void SetException(std::exception_ptr&&) noexcept;
62
63private:
64 bool has_value_{false};
65 std::exception_ptr exception_;
66};
67
68template <typename T>
69T ResultStore<T>::Retrieve() {
70 if (value_) {
71 return std::move(*value_);
72 }
73 if (exception_) {
74 std::rethrow_exception(exception_);
75 }
76 throw std::logic_error("result store is not ready");
77}
78
79template <typename T>
80const T& ResultStore<T>::Get() const& {
81 if (value_) {
82 return *value_;
83 }
84 if (exception_) {
85 std::rethrow_exception(exception_);
86 }
87 throw std::logic_error("result store is not ready");
88}
89
90template <typename T>
91void ResultStore<T>::SetValue(const T& value) {
92 value_ = value;
93}
94
95template <typename T>
96void ResultStore<T>::SetValue(T&& value) {
97 value_.emplace(std::move(value));
98}
99
100template <typename T>
101void ResultStore<T>::SetException(std::exception_ptr&& exception) noexcept {
102 exception_ = std::move(exception);
103}
104
105// NOLINTNEXTLINE(readability-make-member-function-const)
106inline void ResultStore<void>::Retrieve() { Get(); }
107
108inline void ResultStore<void>::Get() const& {
109 if (has_value_) {
110 return;
111 }
112 if (exception_) {
113 std::rethrow_exception(exception_);
114 }
115 throw std::logic_error("result store is not ready");
116}
117
118inline void ResultStore<void>::SetValue() noexcept { has_value_ = true; }
119
120inline void ResultStore<void>::SetException(std::exception_ptr&& exception) noexcept {
121 exception_ = std::move(exception);
122}
123
124} // namespace utils
125
126USERVER_NAMESPACE_END