Update basic_waitable_timer to proposed interface.

This commit is contained in:
Christopher Kohlhoff 2014-09-30 19:04:52 +10:00
parent b4bdfd195d
commit 74e12e51ba
24 changed files with 444 additions and 51 deletions

View File

@ -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.
/**

View File

@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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();

View File

@ -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());

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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`.
]
]
]

View File

@ -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`]
[

View File

@ -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);

View File

@ -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