userver: userver/engine/task/task_with_result.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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