C/C++ API Reference
Loading...
Searching...
No Matches
task.h
1// Copyright 2025 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include "pw_assert/assert.h"
17#include "pw_async2/context.h"
18#include "pw_async2/lock.h"
19#include "pw_async2/poll.h"
20#include "pw_containers/intrusive_forward_list.h"
21#include "pw_containers/intrusive_list.h"
22#include "pw_log/tokenized_args.h"
23#include "pw_sync/lock_annotations.h"
24
25namespace pw::async2 {
26
28
30#define PW_ASYNC_TASK_NAME(name) PW_LOG_TOKEN_EXPR("pw_async2", name)
31
32class NativeDispatcherBase;
33
62class Task : public IntrusiveList<Task>::Item {
63 public:
72 explicit constexpr Task(log::Token name = kDefaultName) : name_(name) {}
73
74 Task(const Task&) = delete;
75 Task(Task&&) = delete;
76 Task& operator=(const Task&) = delete;
77 Task& operator=(Task&&) = delete;
78
90 virtual ~Task() = default;
91
101 Poll<> Pend(Context& cx) { return DoPend(cx); }
102
111 bool IsRegistered() const;
112
127 void Deregister() PW_LOCKS_EXCLUDED(impl::dispatcher_lock());
128
129 private:
130 friend class Dispatcher;
131 friend class NativeDispatcherBase;
132 friend class OwnedTask;
133 friend class Waker;
134
135 static constexpr log::Token kDefaultName =
136 PW_LOG_TOKEN("pw_async2", "(anonymous)");
137
138 struct OwnedTag {};
139
140 // Constructor for OwnedTask objects.
141 constexpr Task(log::Token name, OwnedTag)
142 : owned_by_dispatcher_(true), name_(name) {}
143
148 bool TryDeregister() PW_LOCKS_EXCLUDED(impl::dispatcher_lock());
149
167 virtual Poll<> DoPend(Context&) = 0;
168
169 // Sets this task to use the provided dispatcher.
170 void PostTo(NativeDispatcherBase& dispatcher)
171 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock()) {
172 PW_DASSERT(state_ == State::kUnposted);
173 PW_DASSERT(dispatcher_ == nullptr);
174 state_ = State::kWoken;
175 dispatcher_ = &dispatcher;
176 }
177
178 // Clears the task's dispatcher.
179 void Unpost() PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock()) {
180 state_ = State::kUnposted;
181 dispatcher_ = nullptr;
182 RemoveAllWakersLocked();
183 }
184
186 enum RunResult {
188 kActive,
189
191 kDeregistered,
192
194 kCompleted,
195
197 kCompletedNeedsDestroy,
198 };
199
200 // Called by the dispatcher to run this task.
201 // TODO: b/456480489 - remove the unnecessary dispatcher argument when
202 // Dispatcher and NativeDispatcherBase are merged.
203 RunResult RunInDispatcher(Dispatcher& dispatcher)
205
206 // Called by the dispatcher to wake this task. Returns whether the task
207 // actually needed to be woken.
208 [[nodiscard]] bool Wake()
209 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
210
211 // Unlinks all `Waker` objects associated with this `Task.`
212 void RemoveAllWakersLocked()
213 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
214
215 // Adds a `Waker` to the linked list of `Waker` s tracked by this
216 // `Task`.
217 void AddWakerLocked(Waker&)
218 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
219
220 // Removes a `Waker` from the linked list of `Waker`s tracked by this `Task`.
221 //
222 // Precondition: the provided waker *must* be in the list of `Waker`s tracked
223 // by this `Task`.
224 void RemoveWakerLocked(Waker&)
225 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
226
227 enum class State : unsigned char {
228 kUnposted,
229 kRunning,
230 kDeregisteredButRunning,
231 kWoken,
232 kSleeping,
233 };
234
235 // The current state of the task.
236 State state_ PW_GUARDED_BY(impl::dispatcher_lock()) = State::kUnposted;
237
238 bool owned_by_dispatcher_ PW_GUARDED_BY(impl::dispatcher_lock()) = false;
239
240 // A pointer to the dispatcher this task is associated with.
241 //
242 // This will be non-null when `state_` is anything other than `kUnposted`.
243 //
244 // This value must be cleared by the dispatcher upon destruction in order to
245 // prevent null access.
246 NativeDispatcherBase* dispatcher_ PW_GUARDED_BY(impl::dispatcher_lock()) =
247 nullptr;
248
249 // Linked list of `Waker` s that may awaken this `Task`.
250 IntrusiveForwardList<Waker> wakers_ PW_GUARDED_BY(impl::dispatcher_lock());
251
252 // Optional user-facing name for the task. If set, it will be included in
253 // debug logs.
254 log::Token name_;
255};
256
258
259} // namespace pw::async2
Definition: context.h:54
A single-threaded cooperatively scheduled runtime for async tasks.
Definition: dispatcher.h:48
Definition: dispatcher_base.h:47
Definition: owned_task.h:31
Definition: poll.h:60
Definition: task.h:62
virtual ~Task()=default
virtual Poll DoPend(Context &)=0
Poll Pend(Context &cx)
Definition: task.h:101
bool IsRegistered() const
constexpr Task(log::Token name=kDefaultName)
Definition: task.h:72
Definition: waker.h:160
Definition: intrusive_list.h:88
pw::sync::InterruptSpinLock & dispatcher_lock()
Definition: lock.h:33
#define PW_LOG_TOKEN(...)
Definition: tokenized_args.h:63
#define PW_GUARDED_BY(x)
Definition: lock_annotations.h:60
#define PW_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: lock_annotations.h:146
#define PW_LOCKS_EXCLUDED(...)
Definition: lock_annotations.h:176