git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@18 52acb1d6-8a22-11de-b505-999d5b087335
191 lines
4.8 KiB
C++
191 lines
4.8 KiB
C++
//
|
|
// reactive_deadline_timer_service.hpp
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
// Copyright (c) 2003-2005 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)
|
|
//
|
|
|
|
#ifndef BOOST_ASIO_DETAIL_REACTIVE_DEADLINE_TIMER_SERVICE_HPP
|
|
#define BOOST_ASIO_DETAIL_REACTIVE_DEADLINE_TIMER_SERVICE_HPP
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
# pragma once
|
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
|
|
#include <boost/asio/detail/push_options.hpp>
|
|
|
|
#include <boost/asio/detail/push_options.hpp>
|
|
#include <cstddef>
|
|
#include <boost/config.hpp>
|
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
|
#include <boost/asio/detail/pop_options.hpp>
|
|
|
|
#include <boost/asio/error.hpp>
|
|
#include <boost/asio/service_factory.hpp>
|
|
#include <boost/asio/detail/bind_handler.hpp>
|
|
#include <boost/asio/detail/noncopyable.hpp>
|
|
#include <boost/asio/detail/socket_ops.hpp>
|
|
#include <boost/asio/detail/socket_types.hpp>
|
|
|
|
namespace boost {
|
|
namespace asio {
|
|
namespace detail {
|
|
|
|
template <typename Demuxer, typename Time_Traits, typename Reactor>
|
|
class reactive_deadline_timer_service
|
|
{
|
|
public:
|
|
// Implementation structure for a timer.
|
|
struct timer_impl
|
|
: private noncopyable
|
|
{
|
|
boost::posix_time::ptime expiry;
|
|
};
|
|
|
|
// The native type of the timer. This type is dependent on the underlying
|
|
// implementation of the timer service.
|
|
typedef timer_impl* impl_type;
|
|
|
|
// The demuxer type for this service.
|
|
typedef Demuxer demuxer_type;
|
|
|
|
// The time type.
|
|
typedef typename Time_Traits::time_type time_type;
|
|
|
|
// The duration type.
|
|
typedef typename Time_Traits::duration_type duration_type;
|
|
|
|
// Constructor.
|
|
reactive_deadline_timer_service(demuxer_type& d)
|
|
: demuxer_(d),
|
|
reactor_(d.get_service(service_factory<Reactor>()))
|
|
{
|
|
}
|
|
|
|
// Get the demuxer associated with the service.
|
|
demuxer_type& demuxer()
|
|
{
|
|
return demuxer_;
|
|
}
|
|
|
|
// Return a null timer implementation.
|
|
static impl_type null()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Create a new timer implementation.
|
|
void create(impl_type& impl)
|
|
{
|
|
impl = new timer_impl;
|
|
}
|
|
|
|
// Destroy a timer implementation.
|
|
void destroy(impl_type& impl)
|
|
{
|
|
if (impl != null())
|
|
{
|
|
reactor_.cancel_timer(impl);
|
|
delete impl;
|
|
impl = null();
|
|
}
|
|
}
|
|
|
|
// Get the expiry time for the timer as an absolute time.
|
|
time_type expires_at(const impl_type& impl) const
|
|
{
|
|
return Time_Traits::from_utc(impl->expiry);
|
|
}
|
|
|
|
// Set the expiry time for the timer as an absolute time.
|
|
void expires_at(impl_type& impl, const time_type& expiry_time)
|
|
{
|
|
impl->expiry = Time_Traits::to_utc(expiry_time);
|
|
}
|
|
|
|
// Get the expiry time for the timer relative to now.
|
|
duration_type expires_from_now(const impl_type& impl) const
|
|
{
|
|
return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
|
|
}
|
|
|
|
// Set the expiry time for the timer relative to now.
|
|
void expires_from_now(impl_type& impl, const duration_type& expiry_time)
|
|
{
|
|
expires_at(impl, Time_Traits::add(Time_Traits::now(), expiry_time));
|
|
}
|
|
|
|
// Cancel any asynchronous wait operations associated with the timer.
|
|
std::size_t cancel(impl_type& impl)
|
|
{
|
|
return reactor_.cancel_timer(impl);
|
|
}
|
|
|
|
// Perform a blocking wait on the timer.
|
|
void wait(impl_type& impl)
|
|
{
|
|
boost::posix_time::ptime now
|
|
= boost::posix_time::microsec_clock::universal_time();
|
|
while (now < impl->expiry)
|
|
{
|
|
boost::posix_time::time_duration timeout = impl->expiry - now;
|
|
::timeval tv;
|
|
tv.tv_sec = timeout.total_seconds();
|
|
tv.tv_usec = timeout.total_microseconds() % 1000000;
|
|
socket_ops::select(0, 0, 0, 0, &tv);
|
|
now = boost::posix_time::microsec_clock::universal_time();
|
|
}
|
|
}
|
|
|
|
template <typename Handler>
|
|
class wait_handler
|
|
{
|
|
public:
|
|
wait_handler(impl_type& impl, Demuxer& demuxer, Handler handler)
|
|
: impl_(impl),
|
|
demuxer_(demuxer),
|
|
work_(demuxer),
|
|
handler_(handler)
|
|
{
|
|
}
|
|
|
|
void operator()(int result)
|
|
{
|
|
boost::asio::error e(result);
|
|
demuxer_.post(detail::bind_handler(handler_, e));
|
|
}
|
|
|
|
private:
|
|
impl_type& impl_;
|
|
Demuxer& demuxer_;
|
|
typename Demuxer::work work_;
|
|
Handler handler_;
|
|
};
|
|
|
|
// Start an asynchronous wait on the timer.
|
|
template <typename Handler>
|
|
void async_wait(impl_type& impl, Handler handler)
|
|
{
|
|
reactor_.schedule_timer(impl->expiry,
|
|
wait_handler<Handler>(impl, demuxer_, handler), impl);
|
|
}
|
|
|
|
private:
|
|
// The demuxer used for dispatching handlers.
|
|
Demuxer& demuxer_;
|
|
|
|
// The selector that performs event demultiplexing for the provider.
|
|
Reactor& reactor_;
|
|
};
|
|
|
|
} // namespace detail
|
|
} // namespace asio
|
|
} // namespace boost
|
|
|
|
#include <boost/asio/detail/pop_options.hpp>
|
|
|
|
#endif // BOOST_ASIO_DETAIL_REACTIVE_DEADLINE_TIMER_SERVICE_HPP
|