userver: userver/engine/task/shared_task_with_result.hpp Source File
Loading...
Searching...
No Matches
shared_task_with_result.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/task/shared_task_with_result.hpp
4/// @brief @copybrief engine::SharedTaskWithResult
5
6#include <memory>
7#include <stdexcept>
8#include <type_traits>
9#include <utility>
10
11#include <userver/engine/exception.hpp>
12#include <userver/engine/impl/task_context_holder.hpp>
13#include <userver/engine/task/shared_task.hpp>
14#include <userver/engine/task/task_processor_fwd.hpp>
15#include <userver/utils/assert.hpp>
16#include <userver/utils/impl/wrapped_call.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace engine {
21
22/// @brief Asynchronous task with result that has a shared ownership of payload
23///
24/// Multiple coroutines may safely await the task and call
25/// @ref engine::SharedTaskWithResult::Get "Get" concurrently. This includes
26/// coroutines running on different @ref engine::TaskProcessor threads.
27///
28/// ## Example usage:
29///
30/// @snippet core/src/engine/task/shared_task_with_result_test.cpp Sample SharedTaskWithResult usage
31///
32/// @see @ref scripts/docs/en/userver/synchronization.md
33template <typename T>
34class [[nodiscard]] SharedTaskWithResult : public SharedTask {
35public:
36 /// @brief Default constructor
37 ///
38 /// Creates an invalid task.
40
41 /// @brief If the task is still valid and is not finished and this is the last
42 /// shared owner of the payload, cancels the task and waits until it finishes.
44
45 /// @brief Assigns the other task into this.
47
48 /// @brief If this task is still valid and is not finished and other task is
49 /// not the same task as this and this is the
50 /// last shared owner of the payload, cancels the task and waits until it
51 /// finishes before assigning the other. Otherwise just assigns the other task
52 /// into this.
54
55 /// @brief Moves the other task into this, leaving the other in an invalid
56 /// state.
57 SharedTaskWithResult(SharedTaskWithResult&& other) noexcept = default;
58
59 /// @brief If this task is still valid and is not finished and other task is
60 /// not the same task as this and this is the
61 /// last shared owner of the payload, cancels the task and waits until it
62 /// finishes before move assigning the other. Otherwise just move assigns the
63 /// other task into this, leaving the other in an invalid state.
64 SharedTaskWithResult& operator=(SharedTaskWithResult&& other) noexcept = default;
65
66 /// @brief Returns (or rethrows) the result of task invocation.
67 /// Task remains valid after return from this method,
68 /// thread(coro)-safe.
69 /// @returns const T& or void
70 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
71 /// and no TaskCancellationBlockers are present.
72 /// @throws TaskCancelledException
73 /// if no result is available because the task was cancelled
74 decltype(auto) Get() const& noexcept(false) {
76
77 Wait();
80 }
81
82 return utils::impl::CastWrappedCall<T>(GetPayload()).Get();
83 }
84
85 std::add_lvalue_reference<const T> Get() && {
86 static_assert(!sizeof(T*), "Store SharedTaskWithResult before using");
87 }
88
89 /// @cond
90 static constexpr WaitMode kWaitMode = WaitMode::kMultipleAwaiters;
91
92 // For internal use only.
93 explicit SharedTaskWithResult(impl::TaskContextHolder&& context)
94 : SharedTask(std::move(context))
95 {}
96 /// @endcond
97};
98
99} // namespace engine
100
101USERVER_NAMESPACE_END