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 {
36 public:
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.
66 default;
67
68 /// @brief Returns (or rethrows) the result of task invocation.
69 /// Task remains valid after return from this method,
70 /// thread(coro)-safe.
71 /// @returns const T& or void
72 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
73 /// and no TaskCancellationBlockers are present.
74 /// @throws TaskCancelledException
75 /// if no result is available because the task was cancelled
76 decltype(auto) Get() const& noexcept(false) {
78
79 Wait();
82 }
83
84 return utils::impl::CastWrappedCall<T>(GetPayload()).Get();
85 }
86
87 std::add_lvalue_reference<const T> Get() && {
88 static_assert(!sizeof(T*), "Store SharedTaskWithResult before using");
89 }
90
91 /// @cond
92 static constexpr WaitMode kWaitMode = WaitMode::kMultipleWaiters;
93
94 // For internal use only.
95 explicit SharedTaskWithResult(impl::TaskContextHolder&& context)
96 : SharedTask(std::move(context)) {}
97 /// @endcond
98};
99
100} // namespace engine
101
102USERVER_NAMESPACE_END