Update basic_waitable_timer to proposed interface.
This commit is contained in:
parent
b4bdfd195d
commit
74e12e51ba
@ -54,7 +54,7 @@ namespace asio {
|
||||
* asio::steady_timer timer(io_service);
|
||||
*
|
||||
* // Set an expiry time relative to now.
|
||||
* timer.expires_from_now(std::chrono::seconds(5));
|
||||
* timer.expires_after(std::chrono::seconds(5));
|
||||
*
|
||||
* // Wait for the timer to expire.
|
||||
* timer.wait();
|
||||
@ -91,7 +91,7 @@ namespace asio {
|
||||
* @code
|
||||
* void on_some_event()
|
||||
* {
|
||||
* if (my_timer.expires_from_now(seconds(5)) > 0)
|
||||
* if (my_timer.expires_after(seconds(5)) > 0)
|
||||
* {
|
||||
* // We managed to cancel the timer. Start new asynchronous wait.
|
||||
* my_timer.async_wait(on_timeout);
|
||||
@ -111,7 +111,7 @@ namespace asio {
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @li The asio::basic_waitable_timer::expires_from_now() function
|
||||
* @li The asio::basic_waitable_timer::expires_after() function
|
||||
* cancels any pending asynchronous waits, and 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
|
||||
@ -127,6 +127,9 @@ class basic_waitable_timer
|
||||
: public basic_io_object<WaitableTimerService>
|
||||
{
|
||||
public:
|
||||
/// The executor type.
|
||||
typedef asio::io_service::executor_type executor_type;
|
||||
|
||||
/// The clock type.
|
||||
typedef Clock clock_type;
|
||||
|
||||
@ -142,8 +145,8 @@ public:
|
||||
/// 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.
|
||||
* expires_at() or expires_after() functions must be called to set an expiry
|
||||
* time before the timer can be waited on.
|
||||
*
|
||||
* @param io_service The io_service object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
@ -187,11 +190,46 @@ public:
|
||||
: basic_io_object<WaitableTimerService>(io_service)
|
||||
{
|
||||
asio::error_code ec;
|
||||
this->get_service().expires_from_now(
|
||||
this->get_service().expires_after(
|
||||
this->get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_from_now");
|
||||
asio::detail::throw_error(ec, "expires_after");
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a basic_waitable_timer from another.
|
||||
/**
|
||||
* This constructor moves a timer from one object to another.
|
||||
*
|
||||
* @param other The other basic_waitable_timer object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_waitable_timer(io_service&) constructor.
|
||||
*/
|
||||
basic_waitable_timer(basic_waitable_timer&& other)
|
||||
: basic_io_object<WaitableTimerService>(
|
||||
ASIO_MOVE_CAST(basic_waitable_timer)(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_waitable_timer from another.
|
||||
/**
|
||||
* This assignment operator moves a timer from one object to another.
|
||||
*
|
||||
* @param other The other basic_waitable_timer object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_waitable_timer(io_service&) constructor.
|
||||
*/
|
||||
basic_waitable_timer& operator=(basic_waitable_timer&& other)
|
||||
{
|
||||
basic_io_object<WaitableTimerService>::operator=(
|
||||
ASIO_MOVE_CAST(basic_waitable_timer)(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Cancel any asynchronous operations that are waiting on the timer.
|
||||
/**
|
||||
* This function forces the completion of any pending asynchronous wait
|
||||
@ -311,7 +349,9 @@ public:
|
||||
return this->get_service().cancel_one(this->get_implementation(), ec);
|
||||
}
|
||||
|
||||
/// Get the timer's expiry time as an absolute time.
|
||||
#if defined(ASIO_NO_DEPRECATED)
|
||||
/// (Deprecated: Use expiry().) 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.
|
||||
@ -320,6 +360,17 @@ public:
|
||||
{
|
||||
return this->get_service().expires_at(this->get_implementation());
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
/// 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_point expiry() const
|
||||
{
|
||||
return this->get_service().expiry(this->get_implementation());
|
||||
}
|
||||
|
||||
/// Set the timer's expiry time as an absolute time.
|
||||
/**
|
||||
@ -381,7 +432,68 @@ public:
|
||||
this->get_implementation(), expiry_time, ec);
|
||||
}
|
||||
|
||||
/// Get the timer's expiry time relative to now.
|
||||
/// Set the timer's expiry time relative to now.
|
||||
/**
|
||||
* This function sets the expiry time. Any pending asynchronous wait
|
||||
* operations will be cancelled. The handler for each cancelled operation will
|
||||
* be invoked with the asio::error::operation_aborted error code.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer.
|
||||
*
|
||||
* @return The number of asynchronous operations that were cancelled.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note If the timer has already expired when expires_after() is called,
|
||||
* then the handlers for asynchronous wait operations will:
|
||||
*
|
||||
* @li have already been invoked; or
|
||||
*
|
||||
* @li have been queued for invocation in the near future.
|
||||
*
|
||||
* These handlers can no longer be cancelled, and therefore are passed an
|
||||
* error code that indicates the successful completion of the wait operation.
|
||||
*/
|
||||
std::size_t expires_after(const duration& expiry_time)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->get_service().expires_after(
|
||||
this->get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_after");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Set the timer's expiry time relative to now.
|
||||
/**
|
||||
* This function sets the expiry time. Any pending asynchronous wait
|
||||
* operations will be cancelled. The handler for each cancelled operation will
|
||||
* be invoked with the asio::error::operation_aborted error code.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @return The number of asynchronous operations that were cancelled.
|
||||
*
|
||||
* @note If the timer has already expired when expires_after() is called,
|
||||
* then the handlers for asynchronous wait operations will:
|
||||
*
|
||||
* @li have already been invoked; or
|
||||
*
|
||||
* @li have been queued for invocation in the near future.
|
||||
*
|
||||
* These handlers can no longer be cancelled, and therefore are passed an
|
||||
* error code that indicates the successful completion of the wait operation.
|
||||
*/
|
||||
std::size_t expires_after(const duration& expiry_time,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->get_service().expires_after(
|
||||
this->get_implementation(), expiry_time, ec);
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
/// (Deprecated: Use expiry().) 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.
|
||||
@ -391,7 +503,8 @@ public:
|
||||
return this->get_service().expires_from_now(this->get_implementation());
|
||||
}
|
||||
|
||||
/// Set the timer's expiry time relative to now.
|
||||
/// (Deprecated: Use expires_after().) Set the timer's expiry time relative
|
||||
/// to now.
|
||||
/**
|
||||
* This function sets the expiry time. Any pending asynchronous wait
|
||||
* operations will be cancelled. The handler for each cancelled operation will
|
||||
@ -422,7 +535,8 @@ public:
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Set the timer's expiry time relative to now.
|
||||
/// (Deprecated: Use expires_after().) Set the timer's expiry time relative
|
||||
/// to now.
|
||||
/**
|
||||
* This function sets the expiry time. Any pending asynchronous wait
|
||||
* operations will be cancelled. The handler for each cancelled operation will
|
||||
@ -450,6 +564,7 @@ public:
|
||||
return this->get_service().expires_from_now(
|
||||
this->get_implementation(), expiry_time, ec);
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
/// Perform a blocking wait on the timer.
|
||||
/**
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
/// Get the expiry time for the timer as an absolute time.
|
||||
time_type expires_at(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.expires_at(impl);
|
||||
return service_impl_.expiry(impl);
|
||||
}
|
||||
|
||||
/// Set the expiry time for the timer as an absolute time.
|
||||
@ -118,14 +118,14 @@ public:
|
||||
/// Get the expiry time for the timer relative to now.
|
||||
duration_type expires_from_now(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.expires_from_now(impl);
|
||||
return TimeTraits::subtract(service_impl_.expiry(impl), TimeTraits::now());
|
||||
}
|
||||
|
||||
/// Set the expiry time for the timer relative to now.
|
||||
std::size_t expires_from_now(implementation_type& impl,
|
||||
const duration_type& expiry_time, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.expires_from_now(impl, expiry_time, ec);
|
||||
return service_impl_.expires_after(impl, expiry_time, ec);
|
||||
}
|
||||
|
||||
// Perform a blocking wait on the timer.
|
||||
|
@ -93,6 +93,38 @@ public:
|
||||
cancel(impl, ec);
|
||||
}
|
||||
|
||||
// Move-construct a new serial port implementation.
|
||||
void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
scheduler_.move_timer(timer_queue_, impl.timer_data, other_impl.timer_data);
|
||||
|
||||
impl.expiry = other_impl.expiry;
|
||||
other_impl.expiry = time_type();
|
||||
|
||||
impl.might_have_pending_waits = other_impl.might_have_pending_waits;
|
||||
other_impl.might_have_pending_waits = false;
|
||||
}
|
||||
|
||||
// Move-assign from another serial port implementation.
|
||||
void move_assign(implementation_type& impl,
|
||||
deadline_timer_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
if (this != &other_service)
|
||||
if (impl.might_have_pending_waits)
|
||||
scheduler_.cancel_timer(timer_queue_, impl.timer_data);
|
||||
|
||||
other_service.scheduler_.move_timer(other_service.timer_queue_,
|
||||
impl.timer_data, other_impl.timer_data);
|
||||
|
||||
impl.expiry = other_impl.expiry;
|
||||
other_impl.expiry = time_type();
|
||||
|
||||
impl.might_have_pending_waits = other_impl.might_have_pending_waits;
|
||||
other_impl.might_have_pending_waits = false;
|
||||
}
|
||||
|
||||
// Cancel any asynchronous wait operations associated with the timer.
|
||||
std::size_t cancel(implementation_type& impl, asio::error_code& ec)
|
||||
{
|
||||
@ -131,7 +163,7 @@ public:
|
||||
}
|
||||
|
||||
// Get the expiry time for the timer as an absolute time.
|
||||
time_type expires_at(const implementation_type& impl) const
|
||||
time_type expiry(const implementation_type& impl) const
|
||||
{
|
||||
return impl.expiry;
|
||||
}
|
||||
@ -146,14 +178,8 @@ public:
|
||||
return count;
|
||||
}
|
||||
|
||||
// Get the expiry time for the timer relative to now.
|
||||
duration_type expires_from_now(const implementation_type& impl) const
|
||||
{
|
||||
return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
|
||||
}
|
||||
|
||||
// Set the expiry time for the timer relative to now.
|
||||
std::size_t expires_from_now(implementation_type& impl,
|
||||
std::size_t expires_after(implementation_type& impl,
|
||||
const duration_type& expiry_time, asio::error_code& ec)
|
||||
{
|
||||
return expires_at(impl,
|
||||
|
@ -132,6 +132,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
// Run /dev/poll once until interrupted or events are ready to be dispatched.
|
||||
ASIO_DECL void run(bool block, op_queue<operation>& ops);
|
||||
|
||||
|
@ -152,6 +152,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
// Run epoll once until interrupted or events are ready to be dispatched.
|
||||
ASIO_DECL void run(bool block, op_queue<operation>& ops);
|
||||
|
||||
|
@ -68,6 +68,19 @@ std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -66,6 +66,19 @@ std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -70,6 +70,19 @@ std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -73,6 +73,19 @@ std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -80,6 +80,19 @@ std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_service::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(dispatch_mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -69,6 +69,19 @@ std::size_t winrt_timer_scheduler::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void winrt_timer_scheduler::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(to, ops);
|
||||
queue.move_timer(to, from);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -155,6 +155,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
// Run the kqueue loop.
|
||||
ASIO_DECL void run(bool block, op_queue<operation>& ops);
|
||||
|
||||
|
@ -141,6 +141,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
// Run select once until interrupted or events are ready to be dispatched.
|
||||
ASIO_DECL void run(bool block, op_queue<operation>& ops);
|
||||
|
||||
|
@ -46,7 +46,11 @@ public:
|
||||
class per_timer_data
|
||||
{
|
||||
public:
|
||||
per_timer_data() : next_(0), prev_(0) {}
|
||||
per_timer_data() :
|
||||
heap_index_((std::numeric_limits<std::size_t>::max)()),
|
||||
next_(0), prev_(0)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class timer_queue;
|
||||
@ -188,6 +192,29 @@ public:
|
||||
return num_cancelled;
|
||||
}
|
||||
|
||||
// Move operations from one timer to another, empty timer.
|
||||
void move_timer(per_timer_data& to, per_timer_data& from)
|
||||
{
|
||||
to.op_queue_.push(from.op_queue_);
|
||||
|
||||
to.heap_index_ = from.heap_index_;
|
||||
from.heap_index_ = (std::numeric_limits<std::size_t>::max)();
|
||||
|
||||
if (to.heap_index_ < heap_.size())
|
||||
heap_[to.heap_index_].timer_ = &to;
|
||||
|
||||
if (timers_ == &from)
|
||||
timers_ = &to;
|
||||
if (from.prev_)
|
||||
from.prev_->next_ = &to;
|
||||
if (from.next_)
|
||||
from.next_->prev_= &to;
|
||||
to.next_ = from.next_;
|
||||
to.prev_ = from.prev_;
|
||||
from.next_ = 0;
|
||||
from.prev_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Move the item at the given index up the heap to its correct position.
|
||||
void up_heap(std::size_t index)
|
||||
|
@ -191,6 +191,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
private:
|
||||
#if defined(WINVER) && (WINVER < 0x0500)
|
||||
typedef DWORD dword_ptr_t;
|
||||
|
@ -81,6 +81,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& from);
|
||||
|
||||
private:
|
||||
// Run the select loop in the thread.
|
||||
ASIO_DECL void run_thread();
|
||||
|
@ -148,7 +148,7 @@ public:
|
||||
// cannot allow more than one read operation at a time on the
|
||||
// underlying transport. The pending_read_ timer's expiry is set to
|
||||
// pos_infin if a read is in progress, and neg_infin otherwise.
|
||||
if (core_.pending_read_.expires_at() == core_.neg_infin())
|
||||
if (core_.expiry(core_.pending_read_) == core_.neg_infin())
|
||||
{
|
||||
// Prevent other read operations from being started.
|
||||
core_.pending_read_.expires_at(core_.pos_infin());
|
||||
@ -175,7 +175,7 @@ public:
|
||||
// cannot allow more than one write operation at a time on the
|
||||
// underlying transport. The pending_write_ timer's expiry is set to
|
||||
// pos_infin if a write is in progress, and neg_infin otherwise.
|
||||
if (core_.pending_write_.expires_at() == core_.neg_infin())
|
||||
if (core_.expiry(core_.pending_write_) == core_.neg_infin())
|
||||
{
|
||||
// Prevent other write operations from being started.
|
||||
core_.pending_write_.expires_at(core_.pos_infin());
|
||||
|
@ -75,6 +75,13 @@ struct stream_core
|
||||
{
|
||||
return boost::posix_time::pos_infin;
|
||||
}
|
||||
|
||||
// Helper function to get a timer's expiry time.
|
||||
static asio::deadline_timer::time_type expiry(
|
||||
const asio::deadline_timer& timer)
|
||||
{
|
||||
return timer.expires_at();
|
||||
}
|
||||
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
// Timer used for storing queued read operations.
|
||||
asio::steady_timer pending_read_;
|
||||
@ -93,6 +100,13 @@ struct stream_core
|
||||
{
|
||||
return (asio::steady_timer::time_point::max)();
|
||||
}
|
||||
|
||||
// Helper function to get a timer's expiry time.
|
||||
static asio::steady_timer::time_point expiry(
|
||||
const asio::steady_timer& timer)
|
||||
{
|
||||
return timer.expiry();
|
||||
}
|
||||
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
|
||||
// Buffer space used to prepare output intended for the transport.
|
||||
|
@ -24,7 +24,7 @@ template <typename Clock>
|
||||
struct wait_traits
|
||||
{
|
||||
/// Convert a clock duration into a duration used for waiting.
|
||||
/**
|
||||
/**
|
||||
* @returns @c d.
|
||||
*/
|
||||
static typename Clock::duration to_wait_duration(
|
||||
@ -32,6 +32,21 @@ struct wait_traits
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
/// Convert a clock duration into a duration used for waiting.
|
||||
/**
|
||||
* @returns @c d.
|
||||
*/
|
||||
static typename Clock::duration to_wait_duration(
|
||||
const typename Clock::time_point& t)
|
||||
{
|
||||
typename Clock::time_point now = Clock::now();
|
||||
if (now + Clock::duration::max() < t)
|
||||
return Clock::duration::max();
|
||||
if (now + Clock::duration::min() > t)
|
||||
return Clock::duration::min();
|
||||
return t - now;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -89,6 +89,23 @@ public:
|
||||
service_impl_.destroy(impl);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a new timer implementation.
|
||||
void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_construct(impl, other_impl);
|
||||
}
|
||||
|
||||
/// Move-assign from another timer implementation.
|
||||
void move_assign(implementation_type& impl,
|
||||
waitable_timer_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Cancel any asynchronous wait operations associated with the timer.
|
||||
std::size_t cancel(implementation_type& impl, asio::error_code& ec)
|
||||
{
|
||||
@ -102,10 +119,19 @@ public:
|
||||
return service_impl_.cancel_one(impl, ec);
|
||||
}
|
||||
|
||||
/// Get the expiry time for the timer as an absolute time.
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
/// (Deprecated: Use expiry().) Get the expiry time for the timer as an
|
||||
/// absolute time.
|
||||
time_point expires_at(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.expires_at(impl);
|
||||
return service_impl_.expiry(impl);
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
/// Get the expiry time for the timer as an absolute time.
|
||||
time_point expiry(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.expiry(impl);
|
||||
}
|
||||
|
||||
/// Set the expiry time for the timer as an absolute time.
|
||||
@ -115,18 +141,30 @@ public:
|
||||
return service_impl_.expires_at(impl, expiry_time, ec);
|
||||
}
|
||||
|
||||
/// Get the expiry time for the timer relative to now.
|
||||
duration expires_from_now(const implementation_type& impl) const
|
||||
/// Set the expiry time for the timer relative to now.
|
||||
std::size_t expires_after(implementation_type& impl,
|
||||
const duration& expiry_time, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.expires_from_now(impl);
|
||||
return service_impl_.expires_after(impl, expiry_time, ec);
|
||||
}
|
||||
|
||||
/// Set the expiry time for the timer relative to now.
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
/// (Deprecated: Use expiry().) Get the expiry time for the timer relative to
|
||||
/// now.
|
||||
duration expires_from_now(const implementation_type& impl) const
|
||||
{
|
||||
typedef detail::chrono_time_traits<Clock, WaitTraits> traits;
|
||||
return traits::subtract(service_impl_.expiry(impl), traits::now());
|
||||
}
|
||||
|
||||
/// (Deprecated: Use expires_after().) Set the expiry time for the timer
|
||||
/// relative to now.
|
||||
std::size_t expires_from_now(implementation_type& impl,
|
||||
const duration& expiry_time, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.expires_from_now(impl, expiry_time, ec);
|
||||
return service_impl_.expires_after(impl, expiry_time, ec);
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
// Perform a blocking wait on the timer.
|
||||
void wait(implementation_type& impl, asio::error_code& ec)
|
||||
|
@ -8,8 +8,9 @@
|
||||
[section:WaitTraits Wait traits requirements]
|
||||
|
||||
In the table below, `X` denotes a wait traits class for clock type `Clock`,
|
||||
where `Clock` meets the C++11 type requirements for a clock, and `d` denotes
|
||||
a value of type `Clock::duration`.
|
||||
where `Clock` meets the C++11 type requirements for a clock, `t` denotes a
|
||||
value of type `Clock::time_point`, and `d` denotes a value of type
|
||||
`Clock::duration`.
|
||||
|
||||
[table WaitTraits requirements
|
||||
[[expression] [return type] [assertion/note\npre/post-condition]]
|
||||
@ -18,7 +19,15 @@ a value of type `Clock::duration`.
|
||||
[`Clock::duration`]
|
||||
[
|
||||
Returns the maximum duration to be used for an individual,
|
||||
implementation-defined wait operation.
|
||||
implementation-defined wait operation for the duration `d`.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`X::to_wait_duration(t);`]
|
||||
[`Clock::duration`]
|
||||
[
|
||||
Returns the maximum duration to be used for an individual,
|
||||
implementation-defined wait operation until the time point `t`.
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -42,7 +42,7 @@ value meeting [link asio.reference.WaitHandler `WaitHandler`] requirements.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`a.expires_at(b);`]
|
||||
[`a.expiry(b);`]
|
||||
[`Clock::time_point`]
|
||||
[]
|
||||
]
|
||||
@ -57,16 +57,9 @@ value meeting [link asio.reference.WaitHandler `WaitHandler`] requirements.
|
||||
post: `a.expires_at(b) == t`.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`a.expires_from_now(b);`]
|
||||
[`Clock::duration`]
|
||||
[
|
||||
Returns a value equivalent to `a.expires_at(b) - Clock::now()`.
|
||||
]
|
||||
]
|
||||
[
|
||||
[``
|
||||
a.expires_from_now(b, d, e);
|
||||
a.expires_after(b, d, e);
|
||||
``]
|
||||
[`size_t`]
|
||||
[
|
||||
|
@ -151,10 +151,18 @@ void strand_test()
|
||||
timer timer1(ios, chronons::seconds(3));
|
||||
timer1.wait();
|
||||
ASIO_CHECK(count == 0);
|
||||
#if defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
|
||||
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.expires_at(timer1.expiry() + chronons::seconds(2));
|
||||
#endif defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.wait();
|
||||
ASIO_CHECK(count == 1);
|
||||
#if defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
|
||||
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.expires_at(timer1.expiry() + chronons::seconds(2));
|
||||
#endif defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||
timer1.wait();
|
||||
ASIO_CHECK(count == 2);
|
||||
|
||||
|
@ -55,7 +55,7 @@ void decrement_to_zero(asio::system_timer* t, int* count)
|
||||
|
||||
int before_value = *count;
|
||||
|
||||
t->expires_at(t->expires_at() + chronons::seconds(1));
|
||||
t->expires_at(t->expiry() + chronons::seconds(1));
|
||||
t->async_wait(bindns::bind(decrement_to_zero, t, count));
|
||||
|
||||
// Completion cannot nest, so count value should remain unchanged.
|
||||
@ -119,7 +119,7 @@ void system_timer_test()
|
||||
expected_end = start + seconds(1) + microseconds(500000);
|
||||
ASIO_CHECK(expected_end < end || expected_end == end);
|
||||
|
||||
t2.expires_at(t2.expires_at() + seconds(1));
|
||||
t2.expires_at(t2.expiry() + seconds(1));
|
||||
t2.wait();
|
||||
|
||||
// The timer must block until after its expiry time.
|
||||
@ -129,7 +129,7 @@ void system_timer_test()
|
||||
|
||||
start = now();
|
||||
|
||||
t2.expires_from_now(seconds(1) + microseconds(200000));
|
||||
t2.expires_after(seconds(1) + microseconds(200000));
|
||||
t2.wait();
|
||||
|
||||
// The timer must block until after its expiry time.
|
||||
@ -327,13 +327,13 @@ void system_timer_thread_test()
|
||||
|
||||
asio::thread th(bindns::bind(io_service_run, &ios));
|
||||
|
||||
t2.expires_from_now(chronons::seconds(2));
|
||||
t2.expires_after(chronons::seconds(2));
|
||||
t2.wait();
|
||||
|
||||
t1.expires_from_now(chronons::seconds(2));
|
||||
t1.expires_after(chronons::seconds(2));
|
||||
t1.async_wait(bindns::bind(increment, &count));
|
||||
|
||||
t2.expires_from_now(chronons::seconds(4));
|
||||
t2.expires_after(chronons::seconds(4));
|
||||
t2.wait();
|
||||
|
||||
ios.stop();
|
||||
@ -342,6 +342,39 @@ void system_timer_thread_test()
|
||||
ASIO_CHECK(count == 1);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
asio::system_timer make_timer(asio::io_service& ios, int* count)
|
||||
{
|
||||
asio::system_timer t(ios);
|
||||
t.expires_after(std::chrono::seconds(1));
|
||||
t.async_wait(bindns::bind(increment, count));
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
void system_timer_move_test()
|
||||
{
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
asio::io_service io_service1;
|
||||
asio::io_service io_service2;
|
||||
int count = 0;
|
||||
|
||||
asio::system_timer t1 = make_timer(io_service1, &count);
|
||||
asio::system_timer t2 = make_timer(io_service2, &count);
|
||||
asio::system_timer t3 = std::move(t1);
|
||||
|
||||
t2 = std::move(t1);
|
||||
|
||||
io_service2.run();
|
||||
|
||||
ASIO_CHECK(count == 1);
|
||||
|
||||
io_service1.run();
|
||||
|
||||
ASIO_CHECK(count == 2);
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
}
|
||||
|
||||
ASIO_TEST_SUITE
|
||||
(
|
||||
"system_timer",
|
||||
@ -349,6 +382,7 @@ ASIO_TEST_SUITE
|
||||
ASIO_TEST_CASE(system_timer_cancel_test)
|
||||
ASIO_TEST_CASE(system_timer_custom_allocation_test)
|
||||
ASIO_TEST_CASE(system_timer_thread_test)
|
||||
ASIO_TEST_CASE(system_timer_move_test)
|
||||
)
|
||||
#else // defined(ASIO_HAS_STD_CHRONO)
|
||||
ASIO_TEST_SUITE
|
||||
|
Loading…
Reference in New Issue
Block a user