userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
lazy_value.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/concurrent/lazy_value.hpp
4
/// @brief @copybrief concurrent::LazyValue
5
6
#
include
<
atomic
>
7
#
include
<
exception
>
8
#
include
<
utility
>
9
10
#
include
<
userver
/
engine
/
multi_consumer_event
.
hpp
>
11
#
include
<
userver
/
utils
/
assert
.
hpp
>
12
#
include
<
userver
/
utils
/
move_only_function
.
hpp
>
13
#
include
<
userver
/
utils
/
result_store
.
hpp
>
14
15
USERVER_NAMESPACE_BEGIN
16
17
namespace
concurrent
{
18
19
/// @brief Lazy value computation with multiple consumers.
20
template
<
typename
T>
21
class
LazyValue final {
22
public
:
23
explicit
LazyValue(
utils
::move_only_function<T()> f)
24
: f_(std::move(f))
25
{
26
UASSERT
(f_);
27
}
28
29
LazyValue(
const
LazyValue&) =
delete
;
30
LazyValue(LazyValue&&) =
delete
;
31
LazyValue& operator=(
const
LazyValue&) =
delete
;
32
LazyValue& operator=(LazyValue&&) =
delete
;
33
34
/// @brief Get an already calculated result or calculate it. It is guaranteed that `f` is called exactly once.
35
/// Can be called concurrently from multiple coroutines.
36
///
37
/// @note If `f` throws, it is not re-evaluated on subsequent calls (unlike with `std::once_flag`).
38
///
39
/// @throws Anything `f` throws.
40
const
T&
operator
()();
41
42
private
:
43
utils
::move_only_function<T()> f_;
44
std::atomic<
bool
> started_{
false
};
45
utils
::ResultStore<T> result_;
46
47
engine::MultiConsumerEvent finished_event_;
48
};
49
50
template
<
typename
T>
51
const
T& LazyValue<T>::
operator
()() {
52
if
(finished_event_
.
IsReady
(
)
) {
53
return
result_.Get();
54
}
55
56
const
bool
old = started_.exchange(
true
, std::memory_order_relaxed);
57
if
(!old) {
58
try
{
59
result_.SetValue(f_());
60
}
catch
(...) {
61
result_.SetException(std::current_exception());
62
finished_event_
.
Send
(
)
;
63
throw
;
64
}
65
finished_event_
.
Send
(
)
;
66
}
else
{
67
finished_event_
.
Wait
(
)
;
68
}
69
70
return
result_.Get();
71
}
72
73
}
// namespace concurrent
74
75
USERVER_NAMESPACE_END
userver
concurrent
lazy_value.hpp
Generated on
for userver by
Doxygen
1.17.0