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 using Task::TryGetContextAccessor;
66
67 /// @cond
68 static constexpr WaitMode kWaitMode = WaitMode::kSingleWaiter;
69
70 // For internal use only.
71 explicit TaskWithResult(impl::TaskContextHolder&& context)
72 : Task(std::move(context))
73 {}
74 /// @endcond
75
76 Task AsTask() && {
77 // NOLINTNEXTLINE(cppcoreguidelines-slicing)
78 return std::move(*this);
79 }
80
81private:
82 void EnsureValid() const {
85 "TaskWithResult::Get was called on an invalid task. Note that "
86 "Get invalidates self, so it must be called at most once "
87 "per task"
88 );
89 }
90};
91
92} // namespace engine
93
94USERVER_NAMESPACE_END