1 // Copyright 2023 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
15 #include "pw_async2/dispatcher_native.h"
16
17 #include <mutex>
18 #include <optional>
19
20 #include "pw_assert/check.h"
21 #include "pw_chrono/system_clock.h"
22
23 namespace pw::async2::backend {
24
DoRunUntilStalled(Dispatcher & dispatcher,Task * task)25 Poll<> NativeDispatcher::DoRunUntilStalled(Dispatcher& dispatcher, Task* task) {
26 {
27 std::lock_guard lock(dispatcher_lock());
28 PW_CHECK(task == nullptr || HasPostedTask(*task),
29 "Attempted to run a dispatcher until a task was stalled, "
30 "but that task has not been `Post`ed to that `Dispatcher`.");
31 }
32 while (true) {
33 RunOneTaskResult result = RunOneTask(dispatcher, task);
34 if (result.completed_main_task() || result.completed_all_tasks()) {
35 return Ready();
36 }
37 if (!result.ran_a_task()) {
38 return Pending();
39 }
40 }
41 }
42
DoRunToCompletion(Dispatcher & dispatcher,Task * task)43 void NativeDispatcher::DoRunToCompletion(Dispatcher& dispatcher, Task* task) {
44 {
45 std::lock_guard lock(dispatcher_lock());
46 PW_CHECK(task == nullptr || HasPostedTask(*task),
47 "Attempted to run a dispatcher until a task was complete, "
48 "but that task has not been `Post`ed to that `Dispatcher`.");
49 }
50 while (true) {
51 RunOneTaskResult result = RunOneTask(dispatcher, task);
52 if (result.completed_main_task() || result.completed_all_tasks()) {
53 return;
54 }
55 if (!result.ran_a_task()) {
56 SleepInfo sleep_info = AttemptRequestWake(/*allow_empty=*/false);
57 if (sleep_info.should_sleep()) {
58 notify_.acquire();
59 }
60 }
61 }
62 }
63
64 } // namespace pw::async2::backend
65