// Copyright 2019 The MediaPipe Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef MEDIAPIPE_FRAMEWORK_TOOL_SIMULATION_CLOCK_H_ #define MEDIAPIPE_FRAMEWORK_TOOL_SIMULATION_CLOCK_H_ #include #include #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" #include "mediapipe/framework/deps/clock.h" namespace mediapipe { // A Clock that simulates the passage of time as quickly as possible. // Parallel threads can call Sleep() and be woken in the proper order. // Simulated time can be advanced by calling SleepUntil for the desired // clock time. Clock time does not advance until all woken threads have // finished or gone back to sleep. // // In case multiple threads are scheduled to wake at the same time, they // wake in the order in which they called Sleep(). No thread is permitted // to continue until all earlier threads have finished or entered Sleep. // The result is a single well-defined order of events. Any desired // order of events can be defined by adjusting the precise sleep times. class SimulationClock : public mediapipe::Clock { public: SimulationClock() {} ~SimulationClock() override; // Returns the simulated time. absl::Time TimeNow() override; // Sleeps until the specified duration has elapsed according to this clock. void Sleep(absl::Duration d) override; // Sleeps until the specifed wakeup_time. void SleepUntil(absl::Time wakeup_time) override; // Informs this clock that a woken thread has started running. void ThreadStart(); // Informs this clock that a woken thread has finished running. void ThreadFinish(); protected: // Queue up wake up waiter. void SleepInternal(absl::Time wakeup_time) ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_mutex_); // Advances to the next wake up time if no related threads are running. void TryAdvanceTime() ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_mutex_); // Represents a thread blocked in SleepUntil. struct Waiter { bool sleeping = true; absl::CondVar cond; }; protected: absl::Mutex time_mutex_; absl::Time time_ ABSL_GUARDED_BY(time_mutex_); std::multimap waiters_ ABSL_GUARDED_BY(time_mutex_); int num_running_ ABSL_GUARDED_BY(time_mutex_) = 0; }; } // namespace mediapipe #endif // MEDIAPIPE_FRAMEWORK_TOOL_SIMULATION_CLOCK_H_