|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r63577 - in trunk/boost/asio/detail: . impl
From: chris_at_[hidden]
Date: 2010-07-04 03:37:44
Author: chris_kohlhoff
Date: 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
New Revision: 63577
URL: http://svn.boost.org/trac/boost/changeset/63577
Log:
Eliminate unnecessary uses of hash_map.
Added:
trunk/boost/asio/detail/object_pool.hpp (contents, props changed)
Text files modified:
trunk/boost/asio/detail/deadline_timer_service.hpp | 5
trunk/boost/asio/detail/dev_poll_reactor.hpp | 6
trunk/boost/asio/detail/epoll_reactor.hpp | 31 ++---
trunk/boost/asio/detail/impl/dev_poll_reactor.hpp | 21 ++-
trunk/boost/asio/detail/impl/dev_poll_reactor.ipp | 3
trunk/boost/asio/detail/impl/epoll_reactor.hpp | 23 ++-
trunk/boost/asio/detail/impl/epoll_reactor.ipp | 67 ++++++++-----
trunk/boost/asio/detail/impl/kqueue_reactor.hpp | 23 ++-
trunk/boost/asio/detail/impl/kqueue_reactor.ipp | 67 ++++++++-----
trunk/boost/asio/detail/impl/select_reactor.hpp | 23 ++-
trunk/boost/asio/detail/impl/select_reactor.ipp | 14 +-
trunk/boost/asio/detail/impl/timer_queue.ipp | 8
trunk/boost/asio/detail/impl/win_iocp_io_service.hpp | 14 +-
trunk/boost/asio/detail/kqueue_reactor.hpp | 27 ++---
trunk/boost/asio/detail/select_reactor.hpp | 6
trunk/boost/asio/detail/timer_queue.hpp | 200 +++++++++++++++++++++++----------------
trunk/boost/asio/detail/win_iocp_io_service.hpp | 8 +
17 files changed, 321 insertions(+), 225 deletions(-)
Modified: trunk/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- trunk/boost/asio/detail/deadline_timer_service.hpp (original)
+++ trunk/boost/asio/detail/deadline_timer_service.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -56,6 +56,7 @@
{
time_type expiry;
bool might_have_pending_waits;
+ typename timer_queue<Time_Traits>::per_timer_data timer_data;
};
// Constructor.
@@ -99,7 +100,7 @@
ec = boost::system::error_code();
return 0;
}
- std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
+ std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
impl.might_have_pending_waits = false;
ec = boost::system::error_code();
return count;
@@ -166,7 +167,7 @@
impl.might_have_pending_waits = true;
- scheduler_.schedule_timer(timer_queue_, impl.expiry, p.p, &impl);
+ scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
p.v = p.p = 0;
}
Modified: trunk/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/dev_poll_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -103,12 +103,14 @@
// specified absolute time.
template <typename Time_Traits>
void schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token);
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
// Cancel the timer operations associated with the given token. Returns the
// number of operations that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& queue, void* token);
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
// Run /dev/poll once until interrupted or events are ready to be dispatched.
BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -21,8 +21,8 @@
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/epoll_reactor_fwd.hpp>
-#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/object_pool.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/select_interrupter.hpp>
@@ -46,15 +46,15 @@
connect_op = 1, except_op = 2, max_ops = 3 };
// Per-descriptor queues.
- struct descriptor_state
+ class descriptor_state
{
- descriptor_state() {}
- descriptor_state(const descriptor_state&) {}
- void operator=(const descriptor_state&) {}
-
+ friend class epoll_reactor;
+ friend class object_pool_access;
mutex mutex_;
op_queue<reactor_op> op_queue_[max_ops];
bool shutdown_;
+ descriptor_state* next_;
+ descriptor_state* prev_;
};
// Per-descriptor data.
@@ -111,13 +111,15 @@
// Schedule a new operation in the given timer queue to expire at the
// specified absolute time.
template <typename Time_Traits>
- void schedule_timer(timer_queue<Time_Traits>& timer_queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token);
+ void schedule_timer(timer_queue<Time_Traits>& queue,
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
// Cancel the timer operations associated with the given token. Returns the
// number of operations that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token);
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
// Run epoll once until interrupted or events are ready to be dispatched.
BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
@@ -177,15 +179,8 @@
// Mutex to protect access to the registered descriptors.
mutex registered_descriptors_mutex_;
- // Keep track of all registered descriptors. This code relies on the fact that
- // the hash_map implementation pools deleted nodes, meaning that we can assume
- // our descriptor_state pointer remains valid even after the entry is removed.
- // Technically this is not true for C++98, as that standard says that spliced
- // elements in a list are invalidated. However, C++0x fixes this shortcoming
- // so we'll just assume that C++98 std::list implementations will do the right
- // thing anyway.
- typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
- descriptor_map registered_descriptors_;
+ // Keep track of all registered descriptors.
+ object_pool<descriptor_state> registered_descriptors_;
};
} // namespace detail
Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -39,25 +39,30 @@
template <typename Time_Traits>
void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token)
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
+
+ if (shutdown_)
{
- bool earliest = queue.enqueue_timer(time, op, token);
- io_service_.work_started();
- if (earliest)
- interrupter_.interrupt();
+ io_service_.post_immediate_completion(op);
+ return;
}
+
+ bool earliest = queue.enqueue_timer(time, timer, op);
+ io_service_.work_started();
+ if (earliest)
+ interrupter_.interrupt();
}
template <typename Time_Traits>
std::size_t dev_poll_reactor::cancel_timer(
- timer_queue<Time_Traits>& queue, void* token)
+ typename timer_queue<Time_Traits>::per_timer_data& timer)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
op_queue<operation> ops;
- std::size_t n = queue.cancel_timer(token, ops);
+ std::size_t n = queue.cancel_timer(timer, ops);
lock.unlock();
io_service_.post_deferred_completions(ops);
return n;
Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.ipp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -82,7 +82,10 @@
boost::asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
+ {
+ post_immediate_completion(op);
return;
+ }
if (allow_speculative)
{
Modified: trunk/boost/asio/detail/impl/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -37,25 +37,30 @@
template <typename Time_Traits>
void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token)
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
{
mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
+
+ if (shutdown_)
{
- bool earliest = queue.enqueue_timer(time, op, token);
- io_service_.work_started();
- if (earliest)
- update_timeout();
+ io_service_.post_immediate_completion(op);
+ return;
}
+
+ bool earliest = queue.enqueue_timer(time, timer, op);
+ io_service_.work_started();
+ if (earliest)
+ update_timeout();
}
template <typename Time_Traits>
-std::size_t epoll_reactor::cancel_timer(
- timer_queue<Time_Traits>& queue, void* token)
+std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer)
{
mutex::scoped_lock lock(mutex_);
op_queue<operation> ops;
- std::size_t n = queue.cancel_timer(token, ops);
+ std::size_t n = queue.cancel_timer(timer, ops);
lock.unlock();
io_service_.post_deferred_completions(ops);
return n;
Modified: trunk/boost/asio/detail/impl/epoll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.ipp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -79,14 +79,12 @@
op_queue<operation> ops;
- descriptor_map::iterator iter = registered_descriptors_.begin();
- descriptor_map::iterator end = registered_descriptors_.end();
- while (iter != end)
+ while (descriptor_state* state = registered_descriptors_.first())
{
for (int i = 0; i < max_ops; ++i)
- ops.push(iter->second.op_queue_[i]);
- iter->second.shutdown_ = true;
- ++iter;
+ ops.push(state->op_queue_[i]);
+ state->shutdown_ = true;
+ registered_descriptors_.free(state);
}
timer_queues_.get_all_timers(ops);
@@ -102,10 +100,7 @@
{
mutex::scoped_lock lock(registered_descriptors_mutex_);
- descriptor_map::iterator new_entry = registered_descriptors_.insert(
- std::make_pair(descriptor, descriptor_state())).first;
- descriptor_data = &new_entry->second;
-
+ descriptor_data = registered_descriptors_.alloc();
descriptor_data->shutdown_ = false;
lock.unlock();
@@ -124,9 +119,20 @@
epoll_reactor::per_descriptor_data& descriptor_data,
reactor_op* op, bool allow_speculative)
{
+ if (!descriptor_data)
+ {
+ op->ec_ = boost::asio::error::bad_descriptor;
+ post_immediate_completion(op);
+ return;
+ }
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
if (descriptor_data->shutdown_)
+ {
+ post_immediate_completion(op);
return;
+ }
if (descriptor_data->op_queue_[op_type].empty())
{
@@ -158,6 +164,9 @@
void epoll_reactor::cancel_ops(socket_type,
epoll_reactor::per_descriptor_data& descriptor_data)
{
+ if (!descriptor_data)
+ return;
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
op_queue<operation> ops;
@@ -179,31 +188,39 @@
void epoll_reactor::close_descriptor(socket_type descriptor,
epoll_reactor::per_descriptor_data& descriptor_data)
{
+ if (!descriptor_data)
+ return;
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
- // Remove the descriptor from the set of known descriptors. The descriptor
- // will be automatically removed from the epoll set when it is closed.
- descriptor_data->shutdown_ = true;
-
- op_queue<operation> ops;
- for (int i = 0; i < max_ops; ++i)
+ if (!descriptor_data->shutdown_)
{
- while (reactor_op* op = descriptor_data->op_queue_[i].front())
+ // Remove the descriptor from the set of known descriptors. The descriptor
+ // will be automatically removed from the epoll set when it is closed.
+
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
{
- op->ec_ = boost::asio::error::operation_aborted;
- descriptor_data->op_queue_[i].pop();
- ops.push(op);
+ while (reactor_op* op = descriptor_data->op_queue_[i].front())
+ {
+ op->ec_ = boost::asio::error::operation_aborted;
+ descriptor_data->op_queue_[i].pop();
+ ops.push(op);
+ }
}
- }
- descriptor_lock.unlock();
+ descriptor_data->shutdown_ = true;
- registered_descriptors_.erase(descriptor);
+ descriptor_lock.unlock();
- descriptors_lock.unlock();
+ registered_descriptors_.free(descriptor_data);
+ descriptor_data = 0;
- io_service_.post_deferred_completions(ops);
+ descriptors_lock.unlock();
+
+ io_service_.post_deferred_completions(ops);
+ }
}
void epoll_reactor::run(bool block, op_queue<operation>& ops)
Modified: trunk/boost/asio/detail/impl/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -41,25 +41,30 @@
template <typename Time_Traits>
void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token)
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
+
+ if (shutdown_)
{
- bool earliest = queue.enqueue_timer(time, op, token);
- io_service_.work_started();
- if (earliest)
- interrupter_.interrupt();
+ io_service_.post_immediate_completion(op);
+ return;
}
+
+ bool earliest = queue.enqueue_timer(time, timer, op);
+ io_service_.work_started();
+ if (earliest)
+ interrupter_.interrupt();
}
template <typename Time_Traits>
-std::size_t kqueue_reactor::cancel_timer(
- timer_queue<Time_Traits>& queue, void* token)
+std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
op_queue<operation> ops;
- std::size_t n = queue.cancel_timer(token, ops);
+ std::size_t n = queue.cancel_timer(timer, ops);
lock.unlock();
io_service_.post_deferred_completions(ops);
return n;
Modified: trunk/boost/asio/detail/impl/kqueue_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.ipp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -57,14 +57,12 @@
op_queue<operation> ops;
- descriptor_map::iterator iter = registered_descriptors_.begin();
- descriptor_map::iterator end = registered_descriptors_.end();
- while (iter != end)
+ while (descriptor_state* state = registered_descriptors_.first())
{
for (int i = 0; i < max_ops; ++i)
- ops.push(iter->second.op_queue_[i]);
- iter->second.shutdown_ = true;
- ++iter;
+ ops.push(state->op_queue_[i]);
+ state->shutdown_ = true;
+ registered_descriptors_.free(state);
}
timer_queues_.get_all_timers(ops);
@@ -80,10 +78,7 @@
{
mutex::scoped_lock lock(registered_descriptors_mutex_);
- descriptor_map::iterator new_entry = registered_descriptors_.insert(
- std::make_pair(descriptor, descriptor_state())).first;
- descriptor_data = &new_entry->second;
-
+ descriptor_data = registered_descriptors_.alloc();
descriptor_data->shutdown_ = false;
return 0;
@@ -93,9 +88,20 @@
kqueue_reactor::per_descriptor_data& descriptor_data,
reactor_op* op, bool allow_speculative)
{
+ if (!descriptor_data)
+ {
+ op->ec_ = boost::asio::error::bad_descriptor;
+ post_immediate_completion(op);
+ return;
+ }
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
if (descriptor_data->shutdown_)
+ {
+ post_immediate_completion(op);
return;
+ }
bool first = descriptor_data->op_queue_[op_type].empty();
if (first)
@@ -151,6 +157,9 @@
void kqueue_reactor::cancel_ops(socket_type,
kqueue_reactor::per_descriptor_data& descriptor_data)
{
+ if (!descriptor_data)
+ return;
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
op_queue<operation> ops;
@@ -172,31 +181,39 @@
void kqueue_reactor::close_descriptor(socket_type descriptor,
kqueue_reactor::per_descriptor_data& descriptor_data)
{
+ if (!descriptor_data)
+ return;
+
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
- // Remove the descriptor from the set of known descriptors. The descriptor
- // will be automatically removed from the kqueue set when it is closed.
- descriptor_data->shutdown_ = true;
-
- op_queue<operation> ops;
- for (int i = 0; i < max_ops; ++i)
+ if (!descriptor_data->shutdown_)
{
- while (reactor_op* op = descriptor_data->op_queue_[i].front())
+ // Remove the descriptor from the set of known descriptors. The descriptor
+ // will be automatically removed from the kqueue set when it is closed.
+
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
{
- op->ec_ = boost::asio::error::operation_aborted;
- descriptor_data->op_queue_[i].pop();
- ops.push(op);
+ while (reactor_op* op = descriptor_data->op_queue_[i].front())
+ {
+ op->ec_ = boost::asio::error::operation_aborted;
+ descriptor_data->op_queue_[i].pop();
+ ops.push(op);
+ }
}
- }
- descriptor_lock.unlock();
+ descriptor_data->shutdown_ = true;
- registered_descriptors_.erase(descriptor);
+ descriptor_lock.unlock();
- descriptors_lock.unlock();
+ registered_descriptors_.free(descriptor_data);
+ descriptor_data = 0;
- io_service_.post_deferred_completions(ops);
+ descriptors_lock.unlock();
+
+ io_service_.post_deferred_completions(ops);
+ }
}
void kqueue_reactor::run(bool block, op_queue<operation>& ops)
Modified: trunk/boost/asio/detail/impl/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -43,25 +43,30 @@
template <typename Time_Traits>
void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token)
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
+
+ if (shutdown_)
{
- bool earliest = queue.enqueue_timer(time, op, token);
- io_service_.work_started();
- if (earliest)
- interrupter_.interrupt();
+ io_service_.post_immediate_completion(op);
+ return;
}
+
+ bool earliest = queue.enqueue_timer(time, timer, op);
+ io_service_.work_started();
+ if (earliest)
+ interrupter_.interrupt();
}
template <typename Time_Traits>
-std::size_t select_reactor::cancel_timer(
- timer_queue<Time_Traits>& queue, void* token)
+std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
op_queue<operation> ops;
- std::size_t n = queue.cancel_timer(token, ops);
+ std::size_t n = queue.cancel_timer(timer, ops);
lock.unlock();
io_service_.post_deferred_completions(ops);
return n;
Modified: trunk/boost/asio/detail/impl/select_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.ipp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -99,13 +99,17 @@
select_reactor::per_descriptor_data&, reactor_op* op, bool)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
+
+ if (shutdown_)
{
- bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
- io_service_.work_started();
- if (first)
- interrupter_.interrupt();
+ post_immediate_completion(op);
+ return;
}
+
+ bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+ io_service_.work_started();
+ if (first)
+ interrupter_.interrupt();
}
void select_reactor::cancel_ops(socket_type descriptor,
Modified: trunk/boost/asio/detail/impl/timer_queue.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/timer_queue.ipp (original)
+++ trunk/boost/asio/detail/impl/timer_queue.ipp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -36,9 +36,9 @@
}
bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
- const time_type& time, timer_op* op, void* token)
+ const time_type& time, per_timer_data& timer, timer_op* op)
{
- return impl_.enqueue_timer(time, op, token);
+ return impl_.enqueue_timer(time, timer, op);
}
bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const
@@ -71,9 +71,9 @@
}
std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
- void* timer_token, op_queue<operation>& ops)
+ per_timer_data& timer, op_queue<operation>& ops)
{
- return impl_.cancel_timer(timer_token, ops);
+ return impl_.cancel_timer(timer, ops);
}
} // namespace detail
Modified: trunk/boost/asio/detail/impl/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_io_service.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -73,23 +73,27 @@
template <typename Time_Traits>
void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token)
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
{
// If the service has been shut down we silently discard the timer.
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+ {
+ post_immediate_completion(op);
return;
+ }
mutex::scoped_lock lock(dispatch_mutex_);
- bool earliest = queue.enqueue_timer(time, op, token);
+ bool earliest = queue.enqueue_timer(time, timer, op);
work_started();
if (earliest)
update_timeout();
}
template <typename Time_Traits>
-std::size_t win_iocp_io_service::cancel_timer(
- timer_queue<Time_Traits>& queue, void* token)
+std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer)
{
// If the service has been shut down we silently ignore the cancellation.
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
@@ -97,7 +101,7 @@
mutex::scoped_lock lock(dispatch_mutex_);
op_queue<win_iocp_operation> ops;
- std::size_t n = queue.cancel_timer(token, ops);
+ std::size_t n = queue.cancel_timer(timer, ops);
post_deferred_completions(ops);
return n;
}
Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -24,9 +24,9 @@
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
-#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/kqueue_reactor_fwd.hpp>
#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/object_pool.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/select_interrupter.hpp>
@@ -59,13 +59,13 @@
// Per-descriptor queues.
struct descriptor_state
{
- descriptor_state() {}
- descriptor_state(const descriptor_state&) {}
- void operator=(const descriptor_state&) {}
-
+ friend class kqueue_reactor;
+ friend class object_pool_access;
mutex mutex_;
op_queue<reactor_op> op_queue_[max_ops];
bool shutdown_;
+ descriptor_state* next_;
+ descriptor_state* prev_;
};
// Per-descriptor data.
@@ -123,12 +123,14 @@
// specified absolute time.
template <typename Time_Traits>
void schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token);
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
// Cancel the timer operations associated with the given token. Returns the
// number of operations that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& queue, void* token);
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
// Run the kqueue loop.
BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
@@ -171,15 +173,8 @@
// Mutex to protect access to the registered descriptors.
mutex registered_descriptors_mutex_;
- // Keep track of all registered descriptors. This code relies on the fact that
- // the hash_map implementation pools deleted nodes, meaning that we can assume
- // our descriptor_state pointer remains valid even after the entry is removed.
- // Technically this is not true for C++98, as that standard says that spliced
- // elements in a list are invalidated. However, C++0x fixes this shortcoming
- // so we'll just assume that C++98 std::list implementations will do the right
- // thing anyway.
- typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
- descriptor_map registered_descriptors_;
+ // Keep track of all registered descriptors.
+ object_pool<descriptor_state> registered_descriptors_;
};
} // namespace detail
Added: trunk/boost/asio/detail/object_pool.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/object_pool.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -0,0 +1,148 @@
+//
+// detail/object_pool.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_OBJECT_POOL_HPP
+#define BOOST_ASIO_DETAIL_OBJECT_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Object>
+class object_pool;
+
+class object_pool_access
+{
+public:
+ template <typename Object>
+ static Object* create()
+ {
+ return new Object;
+ }
+
+ template <typename Object>
+ static void destroy(Object* o)
+ {
+ delete o;
+ }
+
+ template <typename Object>
+ static Object*& next(Object* o)
+ {
+ return o->next_;
+ }
+
+ template <typename Object>
+ static Object*& prev(Object* o)
+ {
+ return o->prev_;
+ }
+};
+
+template <typename Object>
+class object_pool
+ : private noncopyable
+{
+public:
+ // Constructor.
+ object_pool()
+ : live_list_(0),
+ free_list_(0)
+ {
+ }
+
+ // Destructor destroys all objects.
+ ~object_pool()
+ {
+ destroy_list(live_list_);
+ destroy_list(free_list_);
+ }
+
+ // Get the object at the start of the live list.
+ Object* first()
+ {
+ return live_list_;
+ }
+
+ // Allocate a new object.
+ Object* alloc()
+ {
+ Object* o = free_list_;
+ if (o)
+ free_list_ = object_pool_access::next(free_list_);
+ else
+ o = object_pool_access::create<Object>();
+
+ object_pool_access::next(o) = live_list_;
+ object_pool_access::prev(o) = 0;
+ if (live_list_)
+ object_pool_access::prev(live_list_) = o;
+ live_list_ = o;
+
+ return o;
+ }
+
+ // Free an object. Moves it to the free list. No destructors are run.
+ void free(Object* o)
+ {
+ if (live_list_ == o)
+ live_list_ = object_pool_access::next(o);
+
+ if (object_pool_access::prev(o))
+ {
+ object_pool_access::next(object_pool_access::prev(o))
+ = object_pool_access::next(o);
+ }
+
+ if (object_pool_access::next(o))
+ {
+ object_pool_access::prev(object_pool_access::next(o))
+ = object_pool_access::prev(o);
+ }
+
+ object_pool_access::next(o) = free_list_;
+ object_pool_access::prev(o) = 0;
+ free_list_ = o;
+ }
+
+private:
+ // Helper function to destroy all elements in a list.
+ void destroy_list(Object* list)
+ {
+ while (list)
+ {
+ Object* o = list;
+ list = object_pool_access::next(o);
+ object_pool_access::destroy(o);
+ }
+ }
+
+ // The list of live objects.
+ Object* live_list_;
+
+ // The free list.
+ Object* free_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_OBJECT_POOL_HPP
Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -112,12 +112,14 @@
// specified absolute time.
template <typename Time_Traits>
void schedule_timer(timer_queue<Time_Traits>& queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token);
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
// Cancel the timer operations associated with the given token. Returns the
// number of operations that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& queue, void* token);
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
// Run select once until interrupted or events are ready to be dispatched.
BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
Modified: trunk/boost/asio/detail/timer_queue.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_queue.hpp (original)
+++ trunk/boost/asio/detail/timer_queue.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -17,11 +17,9 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
-#include <memory>
#include <vector>
#include <boost/config.hpp>
#include <boost/limits.hpp>
-#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/timer_op.hpp>
#include <boost/asio/detail/timer_queue_base.hpp>
@@ -49,6 +47,26 @@
// The duration type.
typedef typename Time_Traits::duration_type duration_type;
+ // Per-timer data.
+ class per_timer_data
+ {
+ public:
+ per_timer_data() : next_(0), prev_(0) {}
+
+ private:
+ friend class timer_queue;
+
+ // The operations waiting on the timer.
+ op_queue<timer_op> op_queue_;
+
+ // The index of the timer in the heap.
+ std::size_t heap_index_;
+
+ // Pointers to adjacent timers in a linked list.
+ per_timer_data* next_;
+ per_timer_data* prev_;
+ };
+
// Constructor.
timer_queue()
: timers_(),
@@ -59,35 +77,44 @@
// Add a new timer to the queue. Returns true if this is the timer that is
// earliest in the queue, in which case the reactor's event demultiplexing
// function call may need to be interrupted and restarted.
- bool enqueue_timer(const time_type& time, timer_op* op, void* token)
+ bool enqueue_timer(const time_type& time, per_timer_data& timer, timer_op* op)
{
// Ensure that there is space for the timer in the heap. We reserve here so
// that the push_back below will not throw due to a reallocation failure.
heap_.reserve(heap_.size() + 1);
- // Insert the new timer into the hash.
- typedef typename hash_map<void*, timer>::iterator iterator;
- typedef typename hash_map<void*, timer>::value_type value_type;
- std::pair<iterator, bool> result =
- timers_.insert(value_type(token, timer()));
- result.first->second.op_queue_.push(op);
- if (result.second)
+ timer.op_queue_.push(op);
+ if (timer.prev_ == 0 && &timer != timers_)
{
+ // Insert the new timer into the linked list of active timers.
+ timer.next_ = timers_;
+ timer.prev_ = 0;
+ if (timers_)
+ timers_->prev_ = &timer;
+ timers_ = &timer;
+
// Put the new timer at the correct position in the heap.
- result.first->second.time_ = time;
- result.first->second.heap_index_ = heap_.size();
- result.first->second.token_ = token;
- heap_.push_back(&result.first->second);
- up_heap(heap_.size() - 1);
+ if (this->is_positive_infinity(time))
+ {
+ timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();
+ return false; // No need to interrupt reactor as timer never expires.
+ }
+ else
+ {
+ timer.heap_index_ = heap_.size();
+ heap_entry entry = { time, &timer };
+ heap_.push_back(entry);
+ up_heap(heap_.size() - 1);
+ }
}
- return (heap_[0] == &result.first->second);
+ return (heap_[0].timer_ == &timer);
}
// Whether there are no timers in the queue.
virtual bool empty() const
{
- return heap_.empty();
+ return timers_ == 0;
}
// Get the time for the timer that is earliest in the queue.
@@ -97,7 +124,7 @@
return max_duration;
boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
- Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+ Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
if (duration > boost::posix_time::milliseconds(max_duration))
duration = boost::posix_time::milliseconds(max_duration);
@@ -116,7 +143,7 @@
return max_duration;
boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
- Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+ Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
if (duration > boost::posix_time::microseconds(max_duration))
duration = boost::posix_time::microseconds(max_duration);
@@ -132,77 +159,54 @@
virtual void get_ready_timers(op_queue<operation>& ops)
{
const time_type now = Time_Traits::now();
- while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
+ while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_))
{
- timer* t = heap_[0];
- ops.push(t->op_queue_);
- remove_timer(t);
+ per_timer_data* timer = heap_[0].timer_;
+ ops.push(timer->op_queue_);
+ remove_timer(*timer);
}
}
// Dequeue all timers.
virtual void get_all_timers(op_queue<operation>& ops)
{
- typename hash_map<void*, timer>::iterator i = timers_.begin();
- typename hash_map<void*, timer>::iterator end = timers_.end();
- while (i != end)
+ while (timers_)
{
- ops.push(i->second.op_queue_);
- typename hash_map<void*, timer>::iterator old_i = i++;
- timers_.erase(old_i);
+ per_timer_data* timer = timers_;
+ timers_ = timers_->next_;
+ ops.push(timer->op_queue_);
+ timer->next_ = 0;
+ timer->prev_ = 0;
}
heap_.clear();
- timers_.clear();
}
// Cancel and dequeue the timers with the given token.
- std::size_t cancel_timer(void* timer_token, op_queue<operation>& ops)
+ std::size_t cancel_timer(per_timer_data& timer, op_queue<operation>& ops)
{
std::size_t num_cancelled = 0;
- typedef typename hash_map<void*, timer>::iterator iterator;
- iterator it = timers_.find(timer_token);
- if (it != timers_.end())
+ if (timer.prev_ != 0 || &timer == timers_)
{
- while (timer_op* op = it->second.op_queue_.front())
+ while (timer_op* op = timer.op_queue_.front())
{
op->ec_ = boost::asio::error::operation_aborted;
- it->second.op_queue_.pop();
+ timer.op_queue_.pop();
ops.push(op);
++num_cancelled;
}
- remove_timer(&it->second);
+ remove_timer(timer);
}
return num_cancelled;
}
private:
- // Structure representing a single outstanding timer.
- struct timer
- {
- timer() {}
- timer(const timer&) {}
- void operator=(const timer&) {}
-
- // The time when the timer should fire.
- time_type time_;
-
- // The operations waiting on the timer.
- op_queue<timer_op> op_queue_;
-
- // The index of the timer in the heap.
- size_t heap_index_;
-
- // The token associated with the timer.
- void* token_;
- };
-
// Move the item at the given index up the heap to its correct position.
- void up_heap(size_t index)
+ void up_heap(std::size_t index)
{
- size_t parent = (index - 1) / 2;
+ std::size_t parent = (index - 1) / 2;
while (index > 0
- && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_))
+ && Time_Traits::less_than(heap_[index].time_, heap_[parent].time_))
{
swap_heap(index, parent);
index = parent;
@@ -211,16 +215,16 @@
}
// Move the item at the given index down the heap to its correct position.
- void down_heap(size_t index)
+ void down_heap(std::size_t index)
{
- size_t child = index * 2 + 1;
+ std::size_t child = index * 2 + 1;
while (child < heap_.size())
{
- size_t min_child = (child + 1 == heap_.size()
+ std::size_t min_child = (child + 1 == heap_.size()
|| Time_Traits::less_than(
- heap_[child]->time_, heap_[child + 1]->time_))
+ heap_[child].time_, heap_[child + 1].time_))
? child : child + 1;
- if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_))
+ if (Time_Traits::less_than(heap_[index].time_, heap_[min_child].time_))
break;
swap_heap(index, min_child);
index = min_child;
@@ -229,20 +233,20 @@
}
// Swap two entries in the heap.
- void swap_heap(size_t index1, size_t index2)
+ void swap_heap(std::size_t index1, std::size_t index2)
{
- timer* tmp = heap_[index1];
+ heap_entry tmp = heap_[index1];
heap_[index1] = heap_[index2];
heap_[index2] = tmp;
- heap_[index1]->heap_index_ = index1;
- heap_[index2]->heap_index_ = index2;
+ heap_[index1].timer_->heap_index_ = index1;
+ heap_[index2].timer_->heap_index_ = index2;
}
// Remove a timer from the heap and list of timers.
- void remove_timer(timer* t)
+ void remove_timer(per_timer_data& timer)
{
// Remove the timer from the heap.
- size_t index = t->heap_index_;
+ std::size_t index = timer.heap_index_;
if (!heap_.empty() && index < heap_.size())
{
if (index == heap_.size() - 1)
@@ -253,27 +257,53 @@
{
swap_heap(index, heap_.size() - 1);
heap_.pop_back();
- size_t parent = (index - 1) / 2;
+ std::size_t parent = (index - 1) / 2;
if (index > 0 && Time_Traits::less_than(
- heap_[index]->time_, heap_[parent]->time_))
+ heap_[index].time_, heap_[parent].time_))
up_heap(index);
else
down_heap(index);
}
}
- // Remove the timer from the hash.
- typedef typename hash_map<void*, timer>::iterator iterator;
- iterator it = timers_.find(t->token_);
- if (it != timers_.end())
- timers_.erase(it);
+ // Remove the timer from the linked list of active timers.
+ if (timers_ == &timer)
+ timers_ = timer.next_;
+ if (timer.prev_)
+ timer.prev_->next_ = timer.next_;
+ if (timer.next_)
+ timer.next_->prev_= timer.prev_;
+ timer.next_ = 0;
+ timer.prev_ = 0;
+ }
+
+ // Determine if the specified absolute time is positive infinity.
+ template <typename Time_Type>
+ static bool is_positive_infinity(const Time_Type& time)
+ {
+ return false;
+ }
+
+ // Determine if the specified absolute time is positive infinity.
+ static bool is_positive_infinity(const boost::posix_time::ptime& time)
+ {
+ return time == boost::posix_time::pos_infin;
}
- // A hash of timer token to linked lists of timers.
- hash_map<void*, timer> timers_;
+ // The head of a linked list of all active timers.
+ per_timer_data* timers_;
+
+ struct heap_entry
+ {
+ // The time when the timer should fire.
+ time_type time_;
+
+ // The associated timer with enqueued operations.
+ per_timer_data* timer_;
+ };
// The heap of timers, with the earliest timer at the front.
- std::vector<timer*> heap_;
+ std::vector<heap_entry> heap_;
};
#if !defined(BOOST_ASIO_HEADER_ONLY)
@@ -292,6 +322,10 @@
// The duration type.
typedef boost::posix_time::time_duration duration_type;
+ // Per-timer data.
+ typedef timer_queue<forwarding_posix_time_traits>::per_timer_data
+ per_timer_data;
+
// Constructor.
BOOST_ASIO_DECL timer_queue();
@@ -302,7 +336,7 @@
// earliest in the queue, in which case the reactor's event demultiplexing
// function call may need to be interrupted and restarted.
BOOST_ASIO_DECL bool enqueue_timer(const time_type& time,
- timer_op* op, void* token);
+ per_timer_data& timer, timer_op* op);
// Whether there are no timers in the queue.
BOOST_ASIO_DECL virtual bool empty() const;
@@ -321,7 +355,7 @@
// Cancel and dequeue the timers with the given token.
BOOST_ASIO_DECL std::size_t cancel_timer(
- void* timer_token, op_queue<operation>& ops);
+ per_timer_data& timer, op_queue<operation>& ops);
private:
timer_queue<forwarding_posix_time_traits> impl_;
Modified: trunk/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_io_service.hpp 2010-07-04 03:37:42 EDT (Sun, 04 Jul 2010)
@@ -148,13 +148,15 @@
// Schedule a new operation in the given timer queue to expire at the
// specified absolute time.
template <typename Time_Traits>
- void schedule_timer(timer_queue<Time_Traits>& timer_queue,
- const typename Time_Traits::time_type& time, timer_op* op, void* token);
+ void schedule_timer(timer_queue<Time_Traits>& queue,
+ const typename Time_Traits::time_type& time,
+ typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
// Cancel the timer associated with the given token. Returns the number of
// handlers that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token);
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
private:
#if defined(WINVER) && (WINVER < 0x0500)
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk