Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
dispatcher_base.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_async2/context.h"
17#include "pw_async2/internal/config.h"
18#include "pw_async2/lock.h"
19#include "pw_async2/task.h"
20#include "pw_async2/waker.h"
21#include "pw_containers/intrusive_list.h"
22#include "pw_metric/metric.h"
23#include "pw_sync/lock_annotations.h"
24#include "pw_sync/mutex.h"
25
26namespace pw::async2 {
27
28// Forward-declare ``Dispatcher``.
29// This concrete type must be provided by a backend.
30class Dispatcher;
31
32template <typename T>
33using PendOutputOf = typename decltype(std::declval<T>().Pend(
34 std::declval<Context&>()))::OutputType;
35
36// Windows GCC doesn't realize the nonvirtual destructor is protected.
38PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wnon-virtual-dtor");
39
48 public:
49 NativeDispatcherBase() = default;
52 NativeDispatcherBase& operator=(NativeDispatcherBase&) = delete;
53 NativeDispatcherBase& operator=(NativeDispatcherBase&&) = delete;
54
55 protected:
56 ~NativeDispatcherBase() = default;
57
59 bool HasPostedTask(Task& task)
60 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock()) {
61 return task.dispatcher_ == this;
62 }
63
71 void Deregister() PW_LOCKS_EXCLUDED(impl::dispatcher_lock());
72
73 void Post(Task& task) PW_LOCKS_EXCLUDED(impl::dispatcher_lock());
74
79 class [[nodiscard]] SleepInfo {
80 friend class NativeDispatcherBase;
81
82 public:
83 bool should_sleep() const { return should_sleep_; }
84
85 private:
86 SleepInfo(bool should_sleep) : should_sleep_(should_sleep) {}
87
88 static SleepInfo DontSleep() { return SleepInfo(false); }
89
90 static SleepInfo Indefinitely() { return SleepInfo(true); }
91
92 bool should_sleep_;
93 };
94
109 PW_LOCKS_EXCLUDED(impl::dispatcher_lock());
110
114 class [[nodiscard]] RunOneTaskResult {
115 public:
116 RunOneTaskResult(bool completed_all_tasks,
117 bool completed_main_task,
118 bool ran_a_task)
119 : completed_all_tasks_(completed_all_tasks),
120 completed_main_task_(completed_main_task),
121 ran_a_task_(ran_a_task) {}
122 bool completed_all_tasks() const { return completed_all_tasks_; }
123 bool completed_main_task() const { return completed_main_task_; }
124 bool ran_a_task() const { return ran_a_task_; }
125
126 private:
127 bool completed_all_tasks_;
128 bool completed_main_task_;
129 bool ran_a_task_;
130 };
131
134 [[nodiscard]] RunOneTaskResult RunOneTask(Dispatcher& dispatcher,
135 Task* task_to_look_for);
136
137 uint32_t tasks_polled() const { return tasks_polled_.value(); }
138 uint32_t tasks_completed() const { return tasks_completed_.value(); }
139 uint32_t sleep_count() const { return sleep_count_.value(); }
140 uint32_t wake_count() const { return wake_count_.value(); }
141
142 private:
143 friend class Dispatcher;
144 friend class Task;
145 friend class Waker;
146
147 void Wake() {
148 wake_count_.Increment();
149 DoWake();
150 }
151
160 virtual void DoWake() = 0;
161
162 static void UnpostTaskList(IntrusiveList<Task>& list)
163 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
164 void RemoveWokenTaskLocked(Task&)
165 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
166 void RemoveSleepingTaskLocked(Task&)
167 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
168
169 // For use by ``Waker``.
170 void WakeTask(Task&) PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
171
172 // For use by ``RunOneTask``.
173 Task* PopWokenTask() PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
174
175 void LogRegisteredTasks();
176
177#if PW_ASYNC2_DEBUG_WAIT_REASON
178 void LogTaskWakers(const Task& task)
179 PW_EXCLUSIVE_LOCKS_REQUIRED(impl::dispatcher_lock());
180#endif // PW_ASYNC2_DEBUG_WAIT_REASON
181
182 // A lock guarding ``Task`` execution.
183 //
184 // This will be acquired prior to pulling any tasks off of the ``Task``
185 // queue, and only released after they have been run and possibly
186 // destroyed.
187 //
188 // If acquiring this lock and ``impl::dispatcher_lock()``, this lock must
189 // be acquired first in order to avoid deadlocks.
190 //
191 // Acquiring this lock may be a slow process, as it must wait until
192 // the running task has finished executing ``Task::Pend``.
193 pw::sync::Mutex task_execution_lock_;
194
195 IntrusiveList<Task> woken_ PW_GUARDED_BY(impl::dispatcher_lock());
196 IntrusiveList<Task> sleeping_ PW_GUARDED_BY(impl::dispatcher_lock());
197 bool wants_wake_ PW_GUARDED_BY(impl::dispatcher_lock()) = false;
198
199 PW_METRIC_GROUP(metrics_, "pw::async2::NativeDispatcherBase");
200 PW_METRIC(metrics_, tasks_polled_, "tasks_polled", 0u);
201 PW_METRIC(metrics_, tasks_completed_, "tasks_completed", 0u);
202 PW_METRIC(metrics_, sleep_count_, "sleep_count", 0u);
203 PW_METRIC(metrics_, wake_count_, "wake_count", 0u);
204};
205
207
208} // namespace pw::async2
A single-threaded cooperatively-scheduled runtime for async tasks.
Definition: dispatcher.h:46
Definition: dispatcher_base.h:79
Definition: dispatcher_base.h:47
RunOneTaskResult RunOneTask(Dispatcher &dispatcher, Task *task_to_look_for)
bool HasPostedTask(Task &task)
Check that a task is posted on this Dispatcher.
Definition: dispatcher_base.h:59
SleepInfo AttemptRequestWake(bool allow_empty)
Definition: task.h:61
Definition: intrusive_list.h:82
Definition: mutex.h:42
#define PW_MODIFY_DIAGNOSTICS_POP()
Definition: compiler.h:191
#define PW_MODIFY_DIAGNOSTIC_GCC(kind, option)
Definition: compiler.h:208
#define PW_MODIFY_DIAGNOSTICS_PUSH()
Definition: compiler.h:186