1 //===-- Alarm.h -------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_HOST_ALARM_H 10 #define LLDB_HOST_ALARM_H 11 12 #include "lldb/Host/HostThread.h" 13 #include "lldb/lldb-types.h" 14 #include "llvm/Support/Chrono.h" 15 16 #include <condition_variable> 17 #include <mutex> 18 19 namespace lldb_private { 20 21 /// \class Alarm abstraction that enables scheduling a callback function after a 22 /// specified timeout. Creating an alarm for a callback returns a Handle that 23 /// can be used to restart or cancel the alarm. 24 class Alarm { 25 public: 26 using Handle = uint64_t; 27 using Callback = std::function<void()>; 28 using TimePoint = llvm::sys::TimePoint<>; 29 using Duration = std::chrono::milliseconds; 30 31 Alarm(Duration timeout, bool run_callback_on_exit = false); 32 ~Alarm(); 33 34 /// Create an alarm for the given callback. The alarm will expire and the 35 /// callback will be called after the timeout. 36 /// 37 /// \returns 38 /// Handle which can be used to restart or cancel the alarm. 39 Handle Create(Callback callback); 40 41 /// Restart the alarm for the given Handle. The alarm will expire and the 42 /// callback will be called after the timeout. 43 /// 44 /// \returns 45 /// True if the alarm was successfully restarted. False if there is no alarm 46 /// for the given Handle or the alarm already expired. 47 bool Restart(Handle handle); 48 49 /// Cancel the alarm for the given Handle. The alarm and its handle will be 50 /// removed. 51 /// 52 /// \returns 53 /// True if the alarm was successfully canceled and the Handle removed. 54 /// False if there is no alarm for the given Handle or the alarm already 55 /// expired. 56 bool Cancel(Handle handle); 57 58 static constexpr Handle INVALID_HANDLE = 0; 59 60 private: 61 /// Helper functions to start, stop and check the status of the alarm thread. 62 /// @{ 63 void StartAlarmThread(); 64 void StopAlarmThread(); 65 bool AlarmThreadRunning(); 66 /// @} 67 68 /// Return an unique, monotonically increasing handle. 69 static Handle GetNextUniqueHandle(); 70 71 /// Helper to compute the next time the alarm thread needs to wake up. 72 TimePoint GetNextExpiration() const; 73 74 /// Alarm entry. 75 struct Entry { 76 Handle handle; 77 Callback callback; 78 TimePoint expiration; 79 80 Entry(Callback callback, TimePoint expiration); 81 bool operator==(const Entry &rhs) { return handle == rhs.handle; } 82 }; 83 84 /// List of alarm entries. 85 std::vector<Entry> m_entries; 86 87 /// Timeout between when an alarm is created and when it fires. 88 Duration m_timeout; 89 90 /// The alarm thread. 91 /// @{ 92 HostThread m_alarm_thread; 93 lldb::thread_result_t AlarmThread(); 94 /// @} 95 96 /// Synchronize access between the alarm thread and the main thread. 97 std::mutex m_alarm_mutex; 98 99 /// Condition variable used to wake up the alarm thread. 100 std::condition_variable m_alarm_cv; 101 102 /// Flag to signal the alarm thread that something changed and we need to 103 /// recompute the next alarm. 104 bool m_recompute_next_alarm = false; 105 106 /// Flag to signal the alarm thread to exit. 107 bool m_exit = false; 108 109 /// Flag to signal we should run all callbacks on exit. 110 bool m_run_callbacks_on_exit = false; 111 }; 112 113 } // namespace lldb_private 114 115 #endif // LLDB_HOST_ALARM_H 116