blob: 74426b3c71da4d9a4b7f913006336ebee320ee06 [file] [log] [blame]
//
// time_t_timer.cpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <asio.hpp>
#include <ctime>
#include <iostream>
// A custom implementation of the Clock concept from the standard C++ library.
struct time_t_clock
{
// The duration type.
typedef asio::chrono::steady_clock::duration duration;
// The duration's underlying arithmetic representation.
typedef duration::rep rep;
// The ratio representing the duration's tick period.
typedef duration::period period;
// An absolute time point represented using the clock.
typedef asio::chrono::time_point<time_t_clock> time_point;
// The clock is not monotonically increasing.
static const bool is_steady = false;
// Get the current time.
static time_point now()
{
return time_point() + asio::chrono::seconds(std::time(0));
}
};
// The asio::basic_waitable_timer template accepts an optional WaitTraits
// template parameter. The underlying time_t clock has one-second granularity,
// so these traits may be customised to reduce the latency between the clock
// ticking over and a wait operation's completion. When the timeout is near
// (less than one second away) we poll the clock more frequently to detect the
// time change closer to when it occurs. The user can select the appropriate
// trade off between accuracy and the increased CPU cost of polling. In extreme
// cases, a zero duration may be returned to make the timers as accurate as
// possible, albeit with 100% CPU usage.
struct time_t_wait_traits
{
// Determine how long until the clock should be next polled to determine
// whether the duration has elapsed.
static time_t_clock::duration to_wait_duration(
const time_t_clock::duration& d)
{
if (d > asio::chrono::seconds(1))
return d - asio::chrono::seconds(1);
else if (d > asio::chrono::seconds(0))
return asio::chrono::milliseconds(10);
else
return asio::chrono::seconds(0);
}
// Determine how long until the clock should be next polled to determine
// whether the absoluate time has been reached.
static time_t_clock::duration to_wait_duration(
const time_t_clock::time_point& t)
{
return to_wait_duration(t - time_t_clock::now());
}
};
typedef asio::basic_waitable_timer<
time_t_clock, time_t_wait_traits> time_t_timer;
void handle_timeout(const asio::error_code&)
{
std::cout << "handle_timeout\n";
}
int main()
{
try
{
asio::io_context io_context;
time_t_timer timer(io_context);
timer.expires_after(asio::chrono::seconds(5));
std::cout << "Starting synchronous wait\n";
timer.wait();
std::cout << "Finished synchronous wait\n";
timer.expires_after(asio::chrono::seconds(5));
std::cout << "Starting asynchronous wait\n";
timer.async_wait(&handle_timeout);
io_context.run();
std::cout << "Finished asynchronous wait\n";
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}