userver: userver/engine/task/task_base.hpp Source File
Loading...
Searching...
No Matches
task_base.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/task/task_base.hpp
4/// @brief @copybrief engine::TaskBase
5
6#include <chrono>
7#include <memory>
8#include <string_view>
9
10#include <userver/engine/deadline.hpp>
11#include <userver/engine/future_status.hpp>
12#include <userver/engine/task/cancel.hpp>
13#include <userver/engine/task/current_task.hpp>
14#include <userver/utils/fast_pimpl.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace utils::impl {
19class WrappedCallBase;
20} // namespace utils::impl
21
22namespace engine {
23namespace impl {
24class TaskContextHolder;
25class TaskContext;
26class DetachedTasksSyncBlock;
27class ContextAccessor;
28} // namespace impl
29
30/// @brief Base class for all the asynchronous tasks
31/// (engine::Task, engine::SharedTask, engine::SharedTaskWithResult,
32/// engine::TaskWithResult, dist_lock::DistLockedTask, ...).
33class [[nodiscard]] TaskBase {
34public:
35 /// Task importance
36 enum class Importance {
37 /// Normal task
38 kNormal,
39
40 /// Critical task. The task will be started regardless of cancellations,
41 /// e.g. due to user request, deadline or TaskProcessor overload. After the
42 /// task starts, it may be cancelled. In particular, if it received any
43 /// cancellation requests before starting, then it will start as cancelled.
45 };
46
47 /// Task state
48 enum class State {
49 kInvalid, ///< Unusable
50 kNew, ///< just created, not registered with task processor
51 kQueued, ///< awaits execution
52 kRunning, ///< executing user code
53 kSuspended, ///< suspended, e.g. waiting for blocking call to complete
54 kCancelled, ///< exited user code because of external request
55 kCompleted, ///< exited user code with return or throw
56 };
57
58 /// Task wait mode
59 enum class WaitMode {
60 /// Can be awaited by at most one task at a time
62 /// Can be awaited by multiple tasks simultaneously
64 };
65
66 /// @brief Checks whether this object owns
67 /// an actual task (not `State::kInvalid`)
68 ///
69 /// An invalid task cannot be used. The task becomes invalid
70 /// after each of the following calls:
71 ///
72 /// 1. the default constructor
73 /// 2. `Detach()`
74 /// 3. `Get()` (see `engine::TaskWithResult`)
75 bool IsValid() const;
76
77 /// Gets the task State
78 State GetState() const;
79
80 static std::string_view GetStateName(State state);
81
82 /// Returns whether the task finished execution
83 bool IsFinished() const;
84
85 /// @brief Suspends execution until the task finishes or caller is cancelled.
86 /// Can be called from coroutine context only. For non-coroutine context use
87 /// BlockingWait().
88 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
89 /// and no TaskCancellationBlockers are present.
90 void Wait() const noexcept(false);
91
92 /// @brief Suspends execution until the task finishes or after the specified
93 /// timeout or until caller is cancelled
94 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
95 /// and no TaskCancellationBlockers are present.
96 template <typename Rep, typename Period>
97 void WaitFor(const std::chrono::duration<Rep, Period>&) const noexcept(false);
98
99 /// @brief Suspends execution until the task finishes or until the specified
100 /// time point is reached or until caller is cancelled
101 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
102 /// and no TaskCancellationBlockers are present.
103 template <typename Clock, typename Duration>
104 void WaitUntil(const std::chrono::time_point<Clock, Duration>&) const noexcept(false);
105
106 /// @brief Suspends execution until the task finishes or until the specified
107 /// deadline is reached or until caller is cancelled
108 /// @throws WaitInterruptedException when `current_task::IsCancelRequested()`
109 /// and no TaskCancellationBlockers are present.
110 void WaitUntil(Deadline) const;
111
112 /// @brief Suspends execution until the task finishes or caller is cancelled.
113 /// Can be called from coroutine context only. For non-coroutine context use
114 /// BlockingWait().
115 /// @returns `false` when `current_task::IsCancelRequested()`
116 /// and no TaskCancellationBlockers are present.
117 [[nodiscard]] bool WaitNothrow() const noexcept;
118
119 /// @brief Suspends execution until the task finishes or until the specified
120 /// deadline is reached or until caller is cancelled
121 /// @returns FutureStatus::kCancelled when `current_task::IsCancelRequested()`
122 /// and no TaskCancellationBlockers are present.
123 [[nodiscard]] FutureStatus WaitNothrowUntil(Deadline) const noexcept;
124
125 /// Queues task cancellation request
127
128 /// @brief Cancels the task and suspends execution until it is finished.
129 /// Can be called from coroutine context only. For non-coroutine context use
130 /// RequestCancel() + BlockingWait().
131 void SyncCancel() noexcept;
132
133 /// Gets task cancellation reason
135
136 /// Waits for the task in non-coroutine context
137 /// (e.g. non-TaskProcessor's std::thread).
138 void BlockingWait() const;
139
140protected:
141 /// @cond
142 // For internal use only.
143 TaskBase();
144
145 // For internal use only.
146 explicit TaskBase(impl::TaskContextHolder&& context);
147
148 // The following special functions must remain protected to forbid slicing
149 // and force those methods implementation in derived classes.
150 TaskBase(TaskBase&&) noexcept;
151 TaskBase& operator=(TaskBase&&) noexcept;
152 TaskBase(const TaskBase&) noexcept;
153 TaskBase& operator=(const TaskBase&) noexcept;
154 ~TaskBase();
155
156 // For internal use only.
157 impl::TaskContext& GetContext() const noexcept;
158
159 // For internal use only.
160 bool HasSameContext(const TaskBase& other) const noexcept;
161
162 // For internal use only.
163 utils::impl::WrappedCallBase& GetPayload() const noexcept;
164
165 // Marks task as invalid. For internal use only.
166 void Invalidate() noexcept;
167
168 void Terminate(TaskCancellationReason) noexcept;
169 /// @endcond
170
171private:
172 friend class impl::DetachedTasksSyncBlock;
173 friend class TaskCancellationToken;
174
175 struct Impl;
176 utils::FastPimpl<Impl, 8, 8> pimpl_;
177};
178
179template <typename Rep, typename Period>
180void TaskBase::WaitFor(const std::chrono::duration<Rep, Period>& duration) const noexcept(false) {
181 WaitUntil(Deadline::FromDuration(duration));
182}
183
184template <typename Clock, typename Duration>
185void TaskBase::WaitUntil(const std::chrono::time_point<Clock, Duration>& until) const noexcept(false) {
186 WaitUntil(Deadline::FromTimePoint(until));
187}
188
189} // namespace engine
190
191USERVER_NAMESPACE_END