userver: userver/engine/task/task_with_result.hpp Source File
Loading...
Searching...
No Matches
task_with_result.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/task/task_with_result.hpp
4/// @brief @copybrief engine::TaskWithResult
5
6#include <memory>
7#include <stdexcept>
8#include <utility>
9
10#include <userver/engine/exception.hpp>
11#include <userver/engine/impl/task_context_holder.hpp>
12#include <userver/engine/task/task.hpp>
13#include <userver/utils/fast_scope_guard.hpp>
14#include <userver/utils/impl/wrapped_call.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace engine {
19
20/// Asynchronous task with result
21///
22/// ## Example usage:
23///
24/// @snippet engine/task/task_with_result_test.cpp Sample TaskWithResult usage
25///
26/// @see @ref scripts/docs/en/userver/synchronization.md
27template <typename T>
28class [[nodiscard]] TaskWithResult : public Task {
29public:
30 /// @brief Default constructor
31 ///
32 /// Creates an invalid task.
33 TaskWithResult() = default;
34
35 TaskWithResult(const TaskWithResult&) = delete;
36 TaskWithResult& operator=(const TaskWithResult&) = delete;
37
38 /// @brief Moves the other task into this, leaving the other in an invalid
39 /// state.
40 TaskWithResult(TaskWithResult&& other) noexcept = default;
41
42 /// @brief If this Task is still valid and is not finished, cancels it and
43 /// waits until it finishes before moving the other. Otherwise just moves the
44 /// other task into this, leaving the other in invalid state.
45 TaskWithResult& operator=(TaskWithResult&& other) noexcept = default;
46
47 /// @brief Returns (or rethrows) the result of task invocation.
48 /// After return from this method the task is not valid.
49 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
50 /// and no TaskCancellationBlockers are present.
51 /// @throws TaskCancelledException
52 /// if no result is available because the task was cancelled
53 T Get() noexcept(false) {
54 EnsureValid();
55
56 Wait();
57 const utils::FastScopeGuard invalidate([this]() noexcept { Invalidate(); });
60 }
61
62 return utils::impl::CastWrappedCall<T>(GetPayload()).Retrieve();
63 }
64
65 /// Satisfies @ref engine::Awaitable, for use with @ref engine::WaitAnyContext and friends.
66 using Task::GetAwaitableToken;
67
68 /// @cond
69 static constexpr WaitMode kWaitMode = WaitMode::kSingleAwaiter;
70
71 // For internal use only.
72 explicit TaskWithResult(impl::TaskContextHolder&& context)
73 : Task(std::move(context))
74 {}
75 /// @endcond
76
77 Task AsTask() && {
78 // NOLINTNEXTLINE(cppcoreguidelines-slicing)
79 return std::move(*this);
80 }
81
82private:
83 void EnsureValid() const {
86 "TaskWithResult::Get was called on an invalid task. Note that "
87 "Get invalidates self, so it must be called at most once "
88 "per task"
89 );
90 }
91};
92
93} // namespace engine
94
95USERVER_NAMESPACE_END