21#include "pw_allocator/allocator.h"
22#include "pw_allocator/shared_ptr.h"
23#include "pw_async2/func_task.h"
24#include "pw_async2/future_task.h"
25#include "pw_async2/internal/lock.h"
26#include "pw_async2/task.h"
27#include "pw_async2/waker.h"
28#include "pw_containers/intrusive_queue.h"
29#include "pw_sync/lock_annotations.h"
32#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
35#include "pw_async2/coro.h"
36#include "pw_async2/coro_task.h"
37#include "pw_async2/fallible_coro_task.h"
110 template <typename T>
113 PW_ASSERT(PostAllocatedTask(task));
121 template <
typename TaskType,
123 typename = std::enable_if_t<std::is_base_of_v<Task, TaskType>>>
125 auto task = allocator.
MakeShared<TaskType>(std::forward<Args>(args)...);
126 if (!PostAllocatedTask(task)) {
143 typename Func = void,
144 int&... kExplicitGuard,
146 typename ActualFunc =
147 std::conditional_t<std::is_void_v<Func>, std::decay_t<Arg>, Func>,
148 typename = std::enable_if_t<!std::is_base_of_v<Task, ActualFunc>>>
151 return Post<FuncTask<ActualFunc>>(allocator, std::forward<Arg>(func));
165 template <
typename Func>
168 return Post<RunOnceTask<Func>>(allocator, std::forward<Func>(func));
181 template <
typename Fut>
184 return Post<FutureTask<Fut>>(allocator, std::forward<Fut>(future));
187#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
196 template <
typename T>
202 return Post<CoroTask<T>>(allocator, std::move(coro));
214 template <
typename T,
216 int&... kExplicitGuard,
218 typename ErrorHandler =
219 std::conditional_t<std::is_void_v<E>, std::decay_t<Arg>, E>>
220 [[nodiscard]] SharedPtr<FallibleCoroTask<T, ErrorHandler>>
Post(
221 Allocator& allocator, Coro<T>&& coro, Arg&& error_handler) {
225 return Post<FallibleCoroTask<T, ErrorHandler>>(
226 allocator, std::move(coro), std::forward<Arg>(error_handler));
240 template <
auto kCoroFunc,
typename... Args>
241 [[nodiscard]]
auto Post(CoroContext coro_cx, Args&&... args) {
242 if constexpr (std::is_member_function_pointer_v<
decltype(kCoroFunc)>) {
243 return PostSharedMemberCoro<kCoroFunc>(coro_cx,
244 std::forward<Args>(args)...);
246 return Post(coro_cx.allocator(),
247 std::invoke(kCoroFunc, coro_cx, std::forward<Args>(args)...));
274 std::lock_guard lock(internal::lock());
275 return PopTaskToRunLocked();
292 std::lock_guard lock(internal::lock());
293 Task* task = PopTaskToRunLocked();
294 has_posted_tasks = task !=
nullptr || !sleeping_.empty();
302 std::lock_guard lock(internal::lock());
304 return PopTaskToRunLocked();
315 return task.RunInDispatcher();
342 void Wake(
Task* task_to_release =
nullptr)
348 task.UnpostAndReleaseRef();
359 void RemoveWokenTaskLocked(
Task& task)
363 void RemoveSleepingTaskLocked(Task& task)
365 sleeping_.remove(task);
367 void AddSleepingTaskLocked(Task& task)
369 sleeping_.push_front(task);
371 void AddWokenTaskLocked(Task& task)
373 woken_.push_back(task);
378 return !woken_.empty() || !sleeping_.empty();
381 void LogTaskWakers(
const Task& task)
386 template <
typename T>
387 bool PostAllocatedTask(
const SharedPtr<T>& task)
389 return PostAllocatedTask(
391 task.GetControlBlock(
392 allocator::internal::ControlBlockHandle::GetInstance_DO_NOT_USE()));
395 bool PostAllocatedTask(Task* task,
396 allocator::internal::ControlBlock* control_block)
399#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
400 template <
auto kCoroMemberFunc,
typename Receiver,
typename... Args>
401 [[nodiscard]]
auto PostSharedMemberCoro(CoroContext coro_cx,
405 return Post(coro_cx.allocator(),
406 std::invoke(kCoroMemberFunc,
407 std::forward<Receiver>(receiver),
409 std::forward<Args>(args)...));
414 IntrusiveQueue<Task> sleeping_
PW_GUARDED_BY(internal::lock());
419 std::atomic<uint8_t> wakes_pending_ = 0;
Definition: allocator.h:45
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:229
Definition: intrusive_queue.h:30
Definition: shared_ptr.h:68
Definition: dispatcher_for_test.h:36
Definition: dispatcher.h:74
Task * PopTaskToRun(bool &has_posted_tasks)
Definition: dispatcher.h:290
SharedPtr< FuncTask< ActualFunc > > Post(Allocator &allocator, Arg &&func)
Definition: dispatcher.h:149
SharedPtr< FutureTask< Fut > > PostFuture(Allocator &allocator, Fut &&future)
Definition: dispatcher.h:182
bool PopAndRunAllReadyTasks()
void PostShared(const SharedPtr< T > &task)
Definition: dispatcher.h:111
Task * PopSingleTaskForThisWake()
Definition: dispatcher.h:301
void LogRegisteredTasks()
SharedPtr< TaskType > Post(Allocator &allocator, Args &&... args)
Definition: dispatcher.h:124
RunTaskResult RunTask(Task &task)
Definition: dispatcher.h:314
Task * PopTaskToRun()
Definition: dispatcher.h:273
SharedPtr< RunOnceTask< Func > > RunOnce(Allocator &allocator, Func &&func)
Definition: dispatcher.h:166
RunTaskResult
Definition: task.h:83
#define PW_GUARDED_BY(x)
Definition: lock_annotations.h:60
#define PW_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: lock_annotations.h:147
#define PW_UNLOCK_FUNCTION(...)
Definition: lock_annotations.h:249
#define PW_LOCKS_EXCLUDED(...)
Definition: lock_annotations.h:178