Files
libremetaverse/libsecondlife/include/boost/asio/basic_deadline_timer.hpp

386 lines
11 KiB
C++
Raw Normal View History

//
// basic_deadline_timer.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_BASIC_DEADLINE_TIMER_HPP
#define BOOST_ASIO_BASIC_DEADLINE_TIMER_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/asio/detail/pop_options.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/service_factory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
namespace boost {
namespace asio {
/// Provides waitable timer functionality.
/**
* The basic_deadline_timer class template provides the ability to perform a
* blocking or asynchronous wait for a timer to expire.
*
* Most applications will use the boost::asio::deadline_timer typedef.
*
* @par Thread Safety:
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Error_Source.
*
* @sa @ref deadline_timer_reset
*
* @par Examples:
* Performing a blocking wait:
* @code
* // Construct a timer without setting an expiry time.
* boost::asio::deadline_timer timer(demuxer);
*
* // Set an expiry time relative to now.
* timer.expires_from_now(boost::posix_time::seconds(5));
*
* // Wait for the timer to expire.
* timer.wait();
* @endcode
*
* @par
* Performing an asynchronous wait:
* @code
* void handler(const boost::asio::error& error)
* {
* if (!error)
* {
* // Timer expired.
* }
* }
*
* ...
*
* // Construct a timer with an absolute expiry time.
* boost::asio::deadline_timer timer(demuxer,
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
*
* // Start an asynchronous wait.
* timer.async_wait(handler);
* @endcode
*/
template <typename Service>
class basic_deadline_timer
: private noncopyable
{
public:
/// The type of the service that will be used to provide timer operations.
typedef Service service_type;
/// The native implementation type of the timer.
typedef typename service_type::impl_type impl_type;
/// The demuxer type for this asynchronous type.
typedef typename service_type::demuxer_type demuxer_type;
/// The type used for reporting errors.
typedef boost::asio::error error_type;
/// The time type.
typedef typename service_type::time_type time_type;
/// The duration type.
typedef typename service_type::duration_type duration_type;
/// Constructor.
/**
* This constructor creates a timer without setting an expiry time. The
* expires_at() or expires_from_now() functions must be called to set an
* expiry time before the timer can be waited on.
*
* @param d The demuxer object that the timer will use to dispatch handlers
* for any asynchronous operations performed on the timer.
*/
explicit basic_deadline_timer(demuxer_type& d)
: service_(d.get_service(service_factory<Service>())),
impl_(service_.null())
{
service_.create(impl_);
}
/// Constructor to set a particular expiry time as an absolute time.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param d The demuxer object that the timer will use to dispatch handlers
* for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
basic_deadline_timer(demuxer_type& d, const time_type& expiry_time)
: service_(d.get_service(service_factory<Service>())),
impl_(service_.null())
{
service_.create(impl_);
destroy_on_block_exit auto_destroy(service_, impl_);
service_.expires_at(impl_, expiry_time);
auto_destroy.cancel();
}
/// Constructor to set a particular expiry time relative to now.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param d The demuxer object that the timer will use to dispatch handlers
* for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
basic_deadline_timer(demuxer_type& d, const duration_type& expiry_time)
: service_(d.get_service(service_factory<Service>())),
impl_(service_.null())
{
service_.create(impl_);
destroy_on_block_exit auto_destroy(service_, impl_);
service_.expires_from_now(impl_, expiry_time);
auto_destroy.cancel();
}
/// Destructor.
~basic_deadline_timer()
{
service_.destroy(impl_);
}
/// Get the demuxer associated with the asynchronous object.
/**
* This function may be used to obtain the demuxer object that the timer uses
* to dispatch handlers for asynchronous operations.
*
* @return A reference to the demuxer object that the timer will use to
* dispatch handlers. Ownership is not transferred to the caller.
*/
demuxer_type& demuxer()
{
return service_.demuxer();
}
/// Get the underlying implementation in the native type.
/**
* This function may be used to obtain the underlying implementation of the
* timer. This is intended to allow access to native timer functionality that
* is not otherwise provided.
*/
impl_type impl()
{
return impl_;
}
/// Get the timer's expiry time as an absolute time.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
time_type expires_at() const
{
return service_.expires_at(impl_);
}
/// Set the timer's expiry time as an absolute time.
/**
* This function sets the expiry time.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @note Modifying the expiry time of a timer while it is active (where
* active means there are asynchronous waits on the timer) has undefined
* behaviour. See @ref deadline_timer_reset for information on how to safely
* alter a timer's expiry in this case.
*/
void expires_at(const time_type& expiry_time)
{
service_.expires_at(impl_, expiry_time);
}
/// Get the timer's expiry time relative to now.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
duration_type expires_from_now() const
{
return service_.expires_from_now(impl_);
}
/// Set the timer's expiry time relative to now.
/**
* This function sets the expiry time.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @note Modifying the expiry time of a timer while it is active (where
* active means there are asynchronous waits on the timer) has undefined
* behaviour. See @ref deadline_timer_reset for information on how to safely
* alter a timer's expiry in this case.
*/
void expires_from_now(const duration_type& expiry_time)
{
service_.expires_from_now(impl_, expiry_time);
}
/// Cancel any asynchronous operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
* operations against the timer. The handler for each cancelled operation
* will be invoked with the boost::asio::error::operation_aborted error code.
*
* Cancelling the timer does not change the expiry time.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t cancel()
{
return service_.cancel(impl_);
}
/// Perform a blocking wait on the timer.
/**
* This function is used to wait for the timer to expire. This function
* blocks and does not return until the timer has expired.
*
* @throws boost::asio::error Thrown on failure.
*/
void wait()
{
service_.wait(impl_);
}
/// Start an asynchronous wait on the timer.
/**
* This function may be used to initiate an asynchronous wait against the
* timer. It always returns immediately.
*
* For each call to async_wait(), the supplied handler will be called exactly
* once. The handler will be called when:
*
* @li The timer has expired.
*
* @li The timer was cancelled, in which case the handler is passed the error
* code boost::asio::error::operation_aborted.
*
* @param handler The handler to be called when the timer expires. Copies
* will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const boost::asio::error& error // Result of operation
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* boost::asio::demuxer::post().
*/
template <typename Handler>
void async_wait(Handler handler)
{
service_.async_wait(impl_, handler);
}
private:
/// The backend service implementation.
service_type& service_;
/// The underlying native implementation.
impl_type impl_;
// Helper class to automatically destroy the implementation on block exit.
class destroy_on_block_exit
{
public:
destroy_on_block_exit(service_type& service, impl_type& impl)
: service_(&service), impl_(impl)
{
}
~destroy_on_block_exit()
{
if (service_)
{
service_->destroy(impl_);
}
}
void cancel()
{
service_ = 0;
}
private:
service_type* service_;
impl_type& impl_;
};
};
/**
* @page deadline_timer_reset Changing an active deadline_timer's expiry time
*
* Changing the expiry time of a timer while there are asynchronous waits on it
* has undefined behaviour. To safely change a timer's expiry, pending
* asynchronous waits need to be cancelled first. This works as follows:
*
* @li The boost::asio::basic_deadline_timer::cancel() function returns the
* number of asynchronous waits that were cancelled. If it returns 0 then you
* were too late and the wait handler has already been executed, or will soon be
* executed. If it returns 1 then the wait handler was successfully cancelled.
*
* @li If a wait handler is cancelled, the boost::asio::error passed to it
* contains the value boost::asio::error::operation_aborted.
*
* For example, to reset a timer's expiry time in response to some event you
* would do something like this:
*
* @code
* void on_some_event()
* {
* if (my_timer.cancel() > 0)
* {
* // We managed to cancel the timer. Set new expiry time.
* my_timer.expires_from_now(seconds(5));
* my_timer.async_wait(on_timeout);
* }
* else
* {
* // Too late, timer has already expired!
* }
* }
*
* void on_timeout(const boost::asio::error& e)
* {
* if (e != boost::asio::error::operation_aborted)
* {
* // Timer was not cancelled, take necessary action.
* }
* }
* @endcode
*
* @sa boost::asio::basic_deadline_timer
*/
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP