Boost logo

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