C/C++ API Reference
Loading...
Searching...
No Matches
dispatcher_for_test.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 <atomic>
17#include <utility>
18
19#include "pw_async2/runnable_dispatcher.h"
20#include "pw_async2/waker.h"
21
22namespace pw::async2 {
23namespace internal {
24
25// This should be updated to work for futures instead of generic pendables.
26template <typename Pendable>
28 public:
29 using value_type = PendOutputOf<Pendable>;
30 PendableAsTaskWithOutput(Pendable& pendable)
31 : pendable_(pendable), output_(Pending()) {}
32
33 Poll<value_type> TakePoll() { return std::move(output_); }
34
35 private:
36 Poll<> DoPend(Context& cx) final {
37 output_ = pendable_.Pend(cx);
38 return output_.Readiness();
39 }
40 Pendable& pendable_;
41 Poll<value_type> output_;
42};
43
44} // namespace internal
45
47
56template <typename Native>
58 public:
61
63 DispatcherForTestFacade& operator=(const DispatcherForTestFacade&) = delete;
64
67
68 ~DispatcherForTestFacade() override;
69
72 void AllowBlocking() { blocking_is_allowed_ = true; }
73
74 template <typename Pendable>
75 Poll<internal::PendOutputOf<Pendable>> RunInTaskUntilStalled(
76 Pendable& pendable) PW_LOCKS_EXCLUDED(internal::lock()) {
78 native().Post(task);
79 native().RunUntilStalled();
80
81 // Ensure that the task is no longer registered, as it will be destroyed
82 // once we return.
83 //
84 // This operation will not block because we are on the dispatcher thread
85 // and the dispatcher is not currently running (we just ran it).
86 task.Deregister();
87
88 return task.TakePoll();
89 }
90
99
103 void Release();
104
107 uint32_t tasks_polled() const {
108 return tasks_polled_.load(std::memory_order_relaxed);
109 }
110
112 uint32_t tasks_completed() const {
113 return tasks_completed_.load(std::memory_order_relaxed);
114 }
115
117 uint32_t wake_count() const {
118 return wake_count_.load(std::memory_order_relaxed);
119 }
120
121 private:
122 // Task to keep the Dispatcher busy in RunToCompletionUntilReleased().
123 class IdleTask : public Task {
124 public:
125 IdleTask() : Task(PW_ASYNC_TASK_NAME("IdleTask")) {}
126
127 ~IdleTask() override;
128
129 void Complete() {
130 should_complete_.store(true, std::memory_order_relaxed);
131 std::move(waker_).Wake();
132 }
133
134 void Reset() {
135 PW_DASSERT(!IsRegistered());
136 should_complete_.store(false, std::memory_order_relaxed);
137 }
138
139 private:
140 Poll<> DoPend(Context& cx) override;
141
142 Waker waker_;
143 std::atomic<bool> should_complete_ = false;
144 };
145
146 // These functions are implemented in dispatcher_for_test.cc for the
147 // NativeDispatcherForTest specialization only.
148 bool DoRunUntilStalled() override;
149
150 void DoWake() override;
151
152 void DoWaitForWake() override;
153
154 RunnableDispatcher& native() { return native_; }
155
156 Native native_;
157 IdleTask idle_task_;
158 bool blocking_is_allowed_ = false;
159 std::atomic<int> blocking_until_released_ = false;
160
161 // TODO: b/401049619 - Optionally provide metrics for production dispatchers.
162 std::atomic<uint32_t> tasks_polled_ = 0u;
163 std::atomic<uint32_t> tasks_completed_ = 0u;
164 std::atomic<uint32_t> wake_count_ = 0u;
165};
166
167} // namespace pw::async2
168
169#include "pw_async2_backend/native_dispatcher_for_test.h"
170
171namespace pw::async2 {
172
177
178} // namespace pw::async2
Definition: context.h:54
Definition: dispatcher_for_test.h:57
void Post(Task &task)
Definition: poll.h:60
Definition: runnable_dispatcher.h:24
Definition: task.h:62
bool IsRegistered() const
Definition: dispatcher_for_test.h:27
#define PW_ASYNC_TASK_NAME(name)
Generates a token for use as a task name.
Definition: task.h:30
constexpr Poll Readiness() const noexcept
Definition: poll.h:140
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
bool RunUntilStalled()
Definition: runnable_dispatcher.h:30
uint32_t wake_count() const
Returns the total number of times the dispatcher has been woken.
Definition: dispatcher_for_test.h:117
DispatcherForTestFacade()=default
DispatcherForTest is default constructible.
uint32_t tasks_polled() const
Definition: dispatcher_for_test.h:107
Poll DoPend(Context &cx) final
Definition: dispatcher_for_test.h:36
uint32_t tasks_completed() const
Returns the total number of tasks the dispatcher has run to completion.
Definition: dispatcher_for_test.h:112
void AllowBlocking()
Definition: dispatcher_for_test.h:72
#define PW_LOCKS_EXCLUDED(...)
Definition: lock_annotations.h:176