16#include "pw_async2/poll.h"
17#include "pw_sync/interrupt_spin_lock.h"
18#include "pw_sync/lock_annotations.h"
19#include "pw_sync/mutex.h"
20#include "pw_toolchain/no_destructor.h"
34 static NoDestructor<pw::sync::InterruptSpinLock> lock;
38class NativeDispatcherBase;
99#define PW_ASYNC_STORE_WAKER(context, waker_out, wait_reason_string) \
101 [[maybe_unused]] constexpr const char* __MUST_BE_STR = wait_reason_string; \
102 context.InternalStoreWaker(waker_out); \
112#define PW_ASYNC_CLONE_WAKER(waker_in, waker_out, wait_reason_string) \
114 [[maybe_unused]] constexpr const char* __MUST_BE_STR = wait_reason_string; \
115 waker_in.InternalCloneInto(waker_out); \
119using PendOutputOf =
typename decltype(std::declval<T>().Pend(
120 std::declval<Context&>()))::OutputType;
122template <
typename,
typename =
void>
123constexpr bool is_pendable =
false;
126constexpr bool is_pendable<T, std::void_t<PendOutputOf<T>>> =
true;
167 Task& operator=(
const Task&) =
delete;
234 bool TryDeregister() PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
265 void RemoveAllWakersLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
269 void AddWakerLocked(
Waker&) PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
276 void RemoveWakerLocked(
Waker&) PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
285 State state_ PW_GUARDED_BY(dispatcher_lock()) = State::kUnposted;
293 NativeDispatcherBase* dispatcher_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
297 Task* prev_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
298 Task* next_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
302 Waker* wakers_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
323 constexpr Waker() =
default;
324 Waker(
Waker&& other)
noexcept PW_LOCKS_EXCLUDED(dispatcher_lock());
331 ~Waker() noexcept { RemoveFromTaskWakerList(); }
342 void Wake() && PW_LOCKS_EXCLUDED(dispatcher_lock());
353 PW_LOCKS_EXCLUDED(dispatcher_lock());
363 [[nodiscard]]
bool IsEmpty() const PW_LOCKS_EXCLUDED(dispatcher_lock());
371 void Clear() PW_LOCKS_EXCLUDED(dispatcher_lock()) {
372 RemoveFromTaskWakerList();
376 Waker(
Task& task) PW_LOCKS_EXCLUDED(dispatcher_lock()) : task_(&task) {
377 InsertIntoTaskWakerList();
380 void InsertIntoTaskWakerList();
381 void InsertIntoTaskWakerListLocked()
382 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
383 void RemoveFromTaskWakerList();
384 void RemoveFromTaskWakerListLocked()
385 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
388 Task* task_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
392 Waker* next_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
419 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock()) {
420 return task.dispatcher_ ==
this;
432 void Post(
Task& task) PW_LOCKS_EXCLUDED(dispatcher_lock());
442 bool should_sleep()
const {
return should_sleep_; }
445 SleepInfo(
bool should_sleep) : should_sleep_(should_sleep) {}
468 PW_LOCKS_EXCLUDED(dispatcher_lock());
476 bool completed_main_task,
478 : completed_all_tasks_(completed_all_tasks),
479 completed_main_task_(completed_main_task),
480 ran_a_task_(ran_a_task) {}
481 bool completed_all_tasks()
const {
return completed_all_tasks_; }
482 bool completed_main_task()
const {
return completed_main_task_; }
483 bool ran_a_task()
const {
return ran_a_task_; }
486 bool completed_all_tasks_;
487 bool completed_main_task_;
494 Task* task_to_look_for);
511 static void UnpostTaskList(
Task*)
512 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
513 static void RemoveTaskFromList(
Task&)
514 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
515 void RemoveWokenTaskLocked(
Task&)
516 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
517 void RemoveSleepingTaskLocked(
Task&)
518 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
521 void AddTaskToWokenList(
Task&) PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
524 void AddTaskToSleepingList(
Task&)
525 PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
528 void WakeTask(
Task&) PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
531 Task* PopWokenTask() PW_EXCLUSIVE_LOCKS_REQUIRED(dispatcher_lock());
544 pw::sync::Mutex task_execution_lock_;
546 Task* first_woken_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
547 Task* last_woken_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
549 Task* sleeping_ PW_GUARDED_BY(dispatcher_lock()) =
nullptr;
550 bool wants_wake_ PW_GUARDED_BY(dispatcher_lock()) = false;
Definition: dispatcher_base.h:52
void InternalStoreWaker(Waker &waker_out)
Context(Dispatcher &dispatcher, Waker &waker)
Definition: dispatcher_base.h:56
Dispatcher & dispatcher()
Definition: dispatcher_base.h:63
A single-threaded cooperatively-scheduled runtime for async tasks.
Definition: dispatcher.h:42
Definition: dispatcher_base.h:473
Definition: dispatcher_base.h:438
Definition: dispatcher_base.h:406
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:418
SleepInfo AttemptRequestWake(bool allow_empty)
Definition: dispatcher_base.h:158
void Destroy()
Definition: dispatcher_base.h:227
virtual Poll DoPend(Context &)=0
Poll Pend(Context &cx)
Definition: dispatcher_base.h:193
bool IsRegistered() const
virtual void DoDestroy()
Definition: dispatcher_base.h:262
Definition: dispatcher_base.h:318
Waker & operator=(Waker &&other) noexcept
void Clear()
Definition: dispatcher_base.h:371
void InternalCloneInto(Waker &waker_out) &
Definition: interrupt_spin_lock.h:48
#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
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27