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();
59 }
60
61 utils::FastScopeGuard invalidate([this]() noexcept { Invalidate(); });
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) : Task(std::move(context)) {}
72 /// @endcond
73
74private:
75 void EnsureValid() const {
78 "TaskWithResult::Get was called on an invalid task. Note that "
79 "Get invalidates self, so it must be called at most once "
80 "per task"
81 );
82 }
83};
84
85} // namespace engine
86
87USERVER_NAMESPACE_END