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