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// clang-format off
23
24/// @brief Asynchronous task with result that has a shared ownership of payload
25///
26/// ## Example usage:
27///
28/// @snippet engine/task/shared_task_with_result_test.cpp Sample SharedTaskWithResult usage
29///
30/// @see @ref scripts/docs/en/userver/synchronization.md
31
32// clang-format on
33
34template <typename T>
35class [[nodiscard]] SharedTaskWithResult : public SharedTask {
36public:
37 /// @brief Default constructor
38 ///
39 /// Creates an invalid task.
41
42 /// @brief If the task is still valid and is not finished and this is the last
43 /// shared owner of the payload, cancels the task and waits until it finishes.
45
46 /// @brief Assigns the other task into this.
48
49 /// @brief If this task is still valid and is not finished and other task is
50 /// not the same task as this and this is the
51 /// last shared owner of the payload, cancels the task and waits until it
52 /// finishes before assigning the other. Otherwise just assigns the other task
53 /// into this.
55
56 /// @brief Moves the other task into this, leaving the other in an invalid
57 /// state.
58 SharedTaskWithResult(SharedTaskWithResult&& other) noexcept = default;
59
60 /// @brief If this task is still valid and is not finished and other task is
61 /// not the same task as this and this is the
62 /// last shared owner of the payload, cancels the task and waits until it
63 /// finishes before move assigning the other. Otherwise just move assigns the
64 /// other task into this, leaving the other in an invalid state.
65 SharedTaskWithResult& operator=(SharedTaskWithResult&& other) noexcept = default;
66
67 /// @brief Returns (or rethrows) the result of task invocation.
68 /// Task remains valid after return from this method,
69 /// thread(coro)-safe.
70 /// @returns const T& or void
71 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
72 /// and no TaskCancellationBlockers are present.
73 /// @throws TaskCancelledException
74 /// if no result is available because the task was cancelled
75 decltype(auto) Get() const& noexcept(false) {
77
78 Wait();
81 }
82
83 return utils::impl::CastWrappedCall<T>(GetPayload()).Get();
84 }
85
86 std::add_lvalue_reference<const T> Get() && {
87 static_assert(!sizeof(T*), "Store SharedTaskWithResult before using");
88 }
89
90 /// @cond
91 static constexpr WaitMode kWaitMode = WaitMode::kMultipleWaiters;
92
93 // For internal use only.
94 explicit SharedTaskWithResult(impl::TaskContextHolder&& context) : SharedTask(std::move(context)) {}
95 /// @endcond
96};
97
98} // namespace engine
99
100USERVER_NAMESPACE_END