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/engine/task/task_processor_fwd.hpp>
14#include <userver/utils/assert.hpp>
15#include <userver/utils/fast_scope_guard.hpp>
16#include <userver/utils/impl/wrapped_call.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace engine {
21
22/// Asynchronous task with result
23///
24/// ## Example usage:
25///
26/// @snippet engine/task/task_with_result_test.cpp Sample TaskWithResult usage
27///
28/// @see @ref scripts/docs/en/userver/synchronization.md
29template <typename T>
30class [[nodiscard]] TaskWithResult : public Task {
31 public:
32 /// @brief Default constructor
33 ///
34 /// Creates an invalid task.
35 TaskWithResult() = default;
36
37 TaskWithResult(const TaskWithResult&) = delete;
38 TaskWithResult& operator=(const TaskWithResult&) = delete;
39
40 /// @brief Moves the other task into this, leaving the other in an invalid
41 /// state.
42 TaskWithResult(TaskWithResult&& other) noexcept = default;
43
44 /// @brief If this Task is still valid and is not finished, cancels it and
45 /// waits until it finishes before moving the other. Otherwise just moves the
46 /// other task into this, leaving the other in invalid state.
47 TaskWithResult& operator=(TaskWithResult&& other) noexcept = default;
48
49 /// @brief Returns (or rethrows) the result of task invocation.
50 /// After return from this method the task is not valid.
51 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
52 /// and no TaskCancellationBlockers are present.
53 /// @throws TaskCancelledException
54 /// if no result is available because the task was cancelled
55 T Get() noexcept(false) {
56 EnsureValid();
57
58 Wait();
61 }
62
63 utils::FastScopeGuard invalidate([this]() noexcept { Invalidate(); });
64 return utils::impl::CastWrappedCall<T>(GetPayload()).Retrieve();
65 }
66
67 using Task::TryGetContextAccessor;
68
69 /// @cond
70 static constexpr WaitMode kWaitMode = WaitMode::kSingleWaiter;
71
72 // For internal use only.
73 explicit TaskWithResult(impl::TaskContextHolder&& context)
74 : Task(std::move(context)) {}
75 /// @endcond
76
77 private:
78 void EnsureValid() const {
80 "TaskWithResult::Get was called on an invalid task. Note that "
81 "Get invalidates self, so it must be called at most once "
82 "per task");
83 }
84};
85
86} // namespace engine
87
88USERVER_NAMESPACE_END