userver
C++ Async Framework
Loading...
Searching...
No Matches
subscribable_futures.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/drivers/subscribable_futures.hpp
4
/// @brief @copybrief drivers::SubscribableFutureWrapper
5
6
#
include
<
boost
/
intrusive_ptr
.
hpp
>
7
#
include
<
boost
/
smart_ptr
/
intrusive_ref_counter
.
hpp
>
8
9
#
include
<
userver
/
engine
/
deadline
.
hpp
>
10
#
include
<
userver
/
engine
/
exception
.
hpp
>
11
#
include
<
userver
/
engine
/
future_status
.
hpp
>
12
#
include
<
userver
/
engine
/
single_consumer_event
.
hpp
>
13
#
include
<
userver
/
engine
/
task
/
cancel
.
hpp
>
14
#
include
<
userver
/
utils
/
make_intrusive_ptr
.
hpp
>
15
16
USERVER_NAMESPACE_BEGIN
17
18
namespace
drivers
{
19
20
namespace
impl {
21
22
struct
EventHolder
final
: boost::intrusive_ref_counter<EventHolder> {
23
engine::SingleConsumerEvent event
{
engine::SingleConsumerEvent::NoAutoReset{}
}
;
24
};
25
26
}
// namespace impl
27
28
/// @ingroup userver_concurrency
29
///
30
/// @brief An adaptor for working with certain external futures.
31
///
32
/// The `SubscribableFuture` must have a `Subscribe(Callback)` method that calls
33
/// the callback when the future is ready. If the future is already ready, then
34
/// `Subscribe` must call the callback immediately. If the promise is dropped
35
/// and will never be fulfilled properly, then the `SubscribableFuture` should
36
/// call the callback anyway.
37
///
38
/// @see drivers::WaitForSubscribableFuture
39
/// @see drivers::TryWaitForSubscribableFuture
40
template
<
typename
SubscribableFuture>
41
class
SubscribableFutureWrapper
final
{
42
public
:
43
explicit
SubscribableFutureWrapper(SubscribableFuture&& future)
44
: original_future_(
static_cast
<SubscribableFuture&&>(future)),
45
event_holder_(
utils
::
make_intrusive_ptr
<
impl
::
EventHolder
>
(
)
)
46
{
47
original_future_.Subscribe([event_holder = event_holder_](
auto
&) { event_holder->event
.
Send
(
)
; });
48
}
49
50
/// @returns the original future
51
SubscribableFuture&
GetFuture
() {
return
original_future_; }
52
53
/// @brief Wait for the future. The result can be retrieved from the original
54
/// future using GetFuture once ready.
55
/// @throws engine::WaitInterruptedException on task cancellation
56
void
Wait
() {
57
if
(
TryWaitUntil
(
engine
::
Deadline
{
}
)
!= engine
::
FutureStatus
::
kReady
) {
58
throw
engine::
WaitInterruptedException
(engine
::
current_task
::
CancellationReason
(
)
);
59
}
60
}
61
62
/// @brief Wait for the future. The result can be retrieved from the original
63
/// future using GetFuture once ready.
64
/// @returns an error code if deadline is exceeded or task is cancelled
65
[[nodiscard]] engine::
FutureStatus
TryWaitUntil
(engine::Deadline deadline) {
66
if
(event_holder_->event.WaitForEventUntil(deadline)) {
67
return
engine
::
FutureStatus
::
kReady
;
68
}
69
return
engine
::
current_task
::
ShouldCancel
(
)
? engine
::
FutureStatus
::
kCancelled
: engine
::
FutureStatus
::
kTimeout
;
70
}
71
72
private
:
73
SubscribableFuture original_future_;
74
boost::intrusive_ptr<impl::EventHolder> event_holder_;
75
};
76
77
/// @ingroup userver_concurrency
78
///
79
/// @brief Waits on the given future as described
80
/// on drivers::SubscribableFutureWrapper.
81
///
82
/// The result can be retrieved from the original future once ready.
83
///
84
/// @throws engine::WaitInterruptedException on task cancellation
85
template
<
typename
SubscribableFuture>
86
void
WaitForSubscribableFuture
(SubscribableFuture&& future) {
87
SubscribableFutureWrapper<SubscribableFuture&>{future}.Wait();
88
}
89
90
/// @ingroup userver_concurrency
91
/// @overload
92
/// @returns an error code if deadline is exceeded or task is cancelled
93
///
94
/// @warning Repeatedly waiting again after `deadline` expiration leads to a
95
/// memory leak, use drivers::SubscribableFutureWrapper instead.
96
template
<
typename
SubscribableFuture>
97
[[nodiscard]] engine::
FutureStatus
TryWaitForSubscribableFuture
(
98
SubscribableFuture&& future,
99
engine::Deadline deadline
100
) {
101
return
SubscribableFutureWrapper<SubscribableFuture&>{future}.TryWaitUntil(deadline);
102
}
103
104
}
// namespace drivers
105
106
USERVER_NAMESPACE_END
userver
drivers
subscribable_futures.hpp
Generated on Wed Apr 1 2026 10:45:31 for userver by
Doxygen
1.13.2