xref: /aosp_15_r20/external/pigweed/pw_async/public/pw_async/fake_dispatcher.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 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 "pw_async/dispatcher.h"
17 #include "pw_async_backend/fake_dispatcher.h"  // nogncheck
18 
19 namespace pw::async::test {
20 
21 /// `FakeDispatcher` is a `Dispatcher` implementation for use in unit tests.
22 ///
23 /// Threading: `FakeDispatcher` is *NOT* thread-safe and, unlike other
24 /// `Dispatcher` implementations. This means that tasks must not be posted from
25 /// multiple threads at once, and tasks cannot be posted from other threads
26 /// while the dispatcher is executing.
27 ///
28 /// Time: `FakeDispatcher` uses simulated time. `RunUntil()` and `RunFor()`
29 /// advance time immediately, and `now()` returns the current simulated time.
30 ///
31 /// To support various `Task` backends, `FakeDispatcher` wraps a
32 /// `backend::NativeFakeDispatcher` that implements standard `FakeDispatcher`
33 /// behavior using `backend::NativeTask` objects.
34 class FakeDispatcher final : public Dispatcher {
35  public:
FakeDispatcher()36   FakeDispatcher() : native_dispatcher_(*this) {}
37 
38   /// Execute all runnable tasks and return without advancing simulated time.
39   /// Returns true iff any tasks were invoked during the run.
RunUntilIdle()40   bool RunUntilIdle() { return native_dispatcher_.RunUntilIdle(); }
41 
42   /// Run the dispatcher until Now() has reached `end_time`, executing all tasks
43   /// that come due before then.
44   /// Returns true iff any tasks were invoked during the run.
RunUntil(chrono::SystemClock::time_point end_time)45   bool RunUntil(chrono::SystemClock::time_point end_time) {
46     return native_dispatcher_.RunUntil(end_time);
47   }
48 
49   /// Run the Dispatcher until `duration` has elapsed, executing all tasks that
50   /// come due in that period.
51   /// Returns true iff any tasks were invoked during the run.
RunFor(chrono::SystemClock::duration duration)52   bool RunFor(chrono::SystemClock::duration duration) {
53     return native_dispatcher_.RunFor(duration);
54   }
55 
56   /// Stop processing tasks. After calling RequestStop(), the next time the
57   /// Dispatcher is run, all waiting Tasks will be dequeued and their
58   /// TaskFunctions called with a PW_STATUS_CANCELLED status.
RequestStop()59   void RequestStop() { native_dispatcher_.RequestStop(); }
60 
61   // Dispatcher overrides:
Post(Task & task)62   void Post(Task& task) override { native_dispatcher_.Post(task); }
PostAfter(Task & task,chrono::SystemClock::duration delay)63   void PostAfter(Task& task, chrono::SystemClock::duration delay) override {
64     native_dispatcher_.PostAfter(task, delay);
65   }
PostAt(Task & task,chrono::SystemClock::time_point time)66   void PostAt(Task& task, chrono::SystemClock::time_point time) override {
67     native_dispatcher_.PostAt(task, time);
68   }
Cancel(Task & task)69   bool Cancel(Task& task) override { return native_dispatcher_.Cancel(task); }
70 
71   // VirtualSystemClock overrides:
now()72   chrono::SystemClock::time_point now() override {
73     return native_dispatcher_.now();
74   }
75 
76   // Returns the inner NativeFakeDispatcher containing backend-specific
77   // state/logic. Only non-portable code should call these methods!
native_type()78   backend::NativeFakeDispatcher& native_type() { return native_dispatcher_; }
native_type()79   const backend::NativeFakeDispatcher& native_type() const {
80     return native_dispatcher_;
81   }
82 
83  private:
84   backend::NativeFakeDispatcher native_dispatcher_;
85 };
86 
87 }  // namespace pw::async::test
88