blob: 23b1ff1af56890f2b745e0415f8a2ef48baa1070 [file] [log] [blame]
//===-- Alarm.h -------------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_HOST_ALARM_H
#define LLDB_HOST_ALARM_H
#include "lldb/Host/HostThread.h"
#include "lldb/lldb-types.h"
#include "llvm/Support/Chrono.h"
#include <condition_variable>
#include <mutex>
namespace lldb_private {
/// \class Alarm abstraction that enables scheduling a callback function after a
/// specified timeout. Creating an alarm for a callback returns a Handle that
/// can be used to restart or cancel the alarm.
class Alarm {
public:
using Handle = uint64_t;
using Callback = std::function<void()>;
using TimePoint = llvm::sys::TimePoint<>;
using Duration = std::chrono::milliseconds;
Alarm(Duration timeout, bool run_callback_on_exit = false);
~Alarm();
/// Create an alarm for the given callback. The alarm will expire and the
/// callback will be called after the timeout.
///
/// \returns
/// Handle which can be used to restart or cancel the alarm.
Handle Create(Callback callback);
/// Restart the alarm for the given Handle. The alarm will expire and the
/// callback will be called after the timeout.
///
/// \returns
/// True if the alarm was successfully restarted. False if there is no alarm
/// for the given Handle or the alarm already expired.
bool Restart(Handle handle);
/// Cancel the alarm for the given Handle. The alarm and its handle will be
/// removed.
///
/// \returns
/// True if the alarm was successfully canceled and the Handle removed.
/// False if there is no alarm for the given Handle or the alarm already
/// expired.
bool Cancel(Handle handle);
static constexpr Handle INVALID_HANDLE = 0;
private:
/// Helper functions to start, stop and check the status of the alarm thread.
/// @{
void StartAlarmThread();
void StopAlarmThread();
bool AlarmThreadRunning();
/// @}
/// Return an unique, monotonically increasing handle.
static Handle GetNextUniqueHandle();
/// Helper to compute the next time the alarm thread needs to wake up.
TimePoint GetNextExpiration() const;
/// Alarm entry.
struct Entry {
Handle handle;
Callback callback;
TimePoint expiration;
Entry(Callback callback, TimePoint expiration);
bool operator==(const Entry &rhs) { return handle == rhs.handle; }
};
/// List of alarm entries.
std::vector<Entry> m_entries;
/// Timeout between when an alarm is created and when it fires.
Duration m_timeout;
/// The alarm thread.
/// @{
HostThread m_alarm_thread;
lldb::thread_result_t AlarmThread();
/// @}
/// Synchronize access between the alarm thread and the main thread.
std::mutex m_alarm_mutex;
/// Condition variable used to wake up the alarm thread.
std::condition_variable m_alarm_cv;
/// Flag to signal the alarm thread that something changed and we need to
/// recompute the next alarm.
bool m_recompute_next_alarm = false;
/// Flag to signal the alarm thread to exit.
bool m_exit = false;
/// Flag to signal we should run all callbacks on exit.
bool m_run_callbacks_on_exit = false;
};
} // namespace lldb_private
#endif // LLDB_HOST_ALARM_H