21#include "pw_allocator/allocator.h"
22#include "pw_allocator/shared_ptr.h"
23#include "pw_async2/context.h"
24#include "pw_async2/func_task.h"
25#include "pw_async2/future_task.h"
26#include "pw_async2/internal/lock.h"
27#include "pw_async2/task.h"
28#include "pw_async2/waker.h"
29#include "pw_containers/intrusive_forward_list.h"
30#include "pw_sync/lock_annotations.h"
33#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
36#include "pw_async2/coro.h"
37#include "pw_async2/coro_task.h"
38#include "pw_async2/fallible_coro_task.h"
90 std::lock_guard lock(internal::lock());
101 template <
typename T>
104 PW_ASSERT(PostAllocatedTask(task));
112 template <
typename TaskType,
114 typename = std::enable_if_t<std::is_base_of_v<Task, TaskType>>>
116 auto task = allocator.
MakeShared<TaskType>(std::forward<Args>(args)...);
117 if (!PostAllocatedTask(task)) {
134 typename Func = void,
135 int&... kExplicitGuard,
137 typename ActualFunc =
138 std::conditional_t<std::is_void_v<Func>, std::decay_t<Arg>, Func>,
139 typename = std::enable_if_t<!std::is_base_of_v<Task, ActualFunc>>>
142 return Post<FuncTask<ActualFunc>>(allocator, std::forward<Arg>(func));
156 template <
typename Func>
159 return Post<RunOnceTask<Func>>(allocator, std::forward<Func>(func));
172 template <
typename Fut>
175 return Post<FutureTask<Fut>>(allocator, std::forward<Fut>(future));
178#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
187 template <
typename T>
193 return Post<CoroTask<T>>(allocator, std::move(coro));
205 template <
typename T,
207 int&... kExplicitGuard,
209 typename ErrorHandler =
210 std::conditional_t<std::is_void_v<E>, std::decay_t<Arg>, E>>
211 [[nodiscard]] SharedPtr<FallibleCoroTask<T, ErrorHandler>>
Post(
212 Allocator& allocator, Coro<T>&& coro, Arg&& error_handler) {
216 return Post<FallibleCoroTask<T, ErrorHandler>>(
217 allocator, std::move(coro), std::forward<Arg>(error_handler));
231 template <
auto kCoroFunc,
typename... Args>
232 [[nodiscard]]
auto Post(CoroContext coro_cx, Args&&... args) {
233 if constexpr (std::is_member_function_pointer_v<
decltype(kCoroFunc)>) {
234 return PostSharedMemberCoro<kCoroFunc>(coro_cx,
235 std::forward<Args>(args)...);
237 return Post(coro_cx.allocator(),
238 std::invoke(kCoroFunc, coro_cx, std::forward<Args>(args)...));
265 std::lock_guard lock(internal::lock());
266 return PopTaskToRunLocked();
283 std::lock_guard lock(internal::lock());
284 Task* task = PopTaskToRunLocked();
285 has_posted_tasks = task !=
nullptr || !sleeping_.empty();
293 std::lock_guard lock(internal::lock());
295 return PopTaskToRunLocked();
306 return task.RunInDispatcher();
340 if (wants_wake_.exchange(
false, std::memory_order_relaxed)) {
354 void RemoveWokenTaskLocked(
Task& task)
358 void RemoveSleepingTaskLocked(Task& task)
360 sleeping_.remove(task);
362 void AddSleepingTaskLocked(Task& task)
364 sleeping_.push_front(task);
370 void LogTaskWakers(
const Task& task)
379 wants_wake_.store(
true, std::memory_order_relaxed);
384 template <
typename T>
385 bool PostAllocatedTask(
const SharedPtr<T>& task)
387 return PostAllocatedTask(
389 task.GetControlBlock(
390 allocator::internal::ControlBlockHandle::GetInstance_DO_NOT_USE()));
393 bool PostAllocatedTask(Task* task,
394 allocator::internal::ControlBlock* control_block)
397#if defined(__cpp_impl_coroutine) && __has_include("pw_async2/coro.h")
398 template <
auto kCoroMemberFunc,
typename Receiver,
typename... Args>
399 [[nodiscard]]
auto PostSharedMemberCoro(CoroContext coro_cx,
402 return Post(coro_cx.allocator(),
403 std::invoke(kCoroMemberFunc,
404 std::forward<Receiver>(receiver),
406 std::forward<Args>(args)...));
412 IntrusiveForwardList<Task> woken_
PW_GUARDED_BY(internal::lock());
413 IntrusiveForwardList<Task> sleeping_
PW_GUARDED_BY(internal::lock());
416 std::atomic<bool> wants_wake_ =
false;
Definition: allocator.h:45
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:229
Definition: intrusive_forward_list.h:99
Definition: shared_ptr.h:68
Definition: dispatcher_for_test.h:36
Definition: dispatcher.h:67
Task * PopTaskToRun(bool &has_posted_tasks)
Definition: dispatcher.h:281
SharedPtr< FuncTask< ActualFunc > > Post(Allocator &allocator, Arg &&func)
Definition: dispatcher.h:140
SharedPtr< FutureTask< Fut > > PostFuture(Allocator &allocator, Fut &&future)
Definition: dispatcher.h:173
bool PopAndRunAllReadyTasks()
void PostShared(const SharedPtr< T > &task)
Definition: dispatcher.h:102
Task * PopSingleTaskForThisWake()
Definition: dispatcher.h:292
virtual ~Dispatcher()
Definition: dispatcher.h:77
void LogRegisteredTasks()
SharedPtr< TaskType > Post(Allocator &allocator, Args &&... args)
Definition: dispatcher.h:115
void Post(Task &task)
Definition: dispatcher.h:88
RunTaskResult RunTask(Task &task)
Definition: dispatcher.h:305
Task * PopTaskToRun()
Definition: dispatcher.h:264
SharedPtr< RunOnceTask< Func > > RunOnce(Allocator &allocator, Func &&func)
Definition: dispatcher.h:157
RunTaskResult
Definition: task.h:38
#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