#pragma once
#include <chrono>
#include <condition_variable>
#include <coroutine>
#include <cstddef>
#include <memory>
#include <mutex>
#include <functional>
#include <stop_token>
#include <thread>
#include <vector>
namespace agent_smith::internal
{
class TimerService
{
private:
struct Entry;
public:
TimerService();
~TimerService();
TimerService(const TimerService&) = delete;
TimerService& operator=(const TimerService&) = delete;
class SleepAwaiter
{
public:
SleepAwaiter(TimerService& service, std::chrono::milliseconds duration,
std::stop_token stop);
bool await_ready() const;
bool await_suspend(std::coroutine_handle<> continuation);
void await_resume() const noexcept {}
private:
TimerService* service_;
std::chrono::milliseconds duration_;
std::shared_ptr<Entry> entry_;
std::unique_ptr<std::stop_callback<std::function<void()>>> callback_;
};
SleepAwaiter sleepFor(std::chrono::milliseconds duration,
std::stop_token stop = {});
private:
struct Entry
{
std::chrono::steady_clock::time_point deadline;
std::coroutine_handle<> continuation = nullptr;
std::stop_token stop;
};
void schedule(const std::shared_ptr<Entry>& entry,
std::coroutine_handle<> continuation);
void worker(std::stop_token stop);
std::mutex mutex_;
std::condition_variable condition_;
std::vector<std::shared_ptr<Entry>> entries_;
std::jthread worker_;
};
} // namespace agent_smith::internal