Boost logo

Boost-Commit :

From: chris_at_[hidden]
Date: 2008-05-05 02:30:15


Author: chris_kohlhoff
Date: 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
New Revision: 45122
URL: http://svn.boost.org/trac/boost/changeset/45122

Log:
Implement custom memory allocation support for reactor-based asynchronous operations.

Added:
   trunk/boost/asio/detail/handler_base_from_member.hpp (contents, props changed)
Text files modified:
   trunk/boost/asio/detail/dev_poll_reactor.hpp | 68 +++++++----
   trunk/boost/asio/detail/epoll_reactor.hpp | 76 ++++++++-----
   trunk/boost/asio/detail/hash_map.hpp | 34 +++++
   trunk/boost/asio/detail/kqueue_reactor.hpp | 84 +++++++++-----
   trunk/boost/asio/detail/reactive_descriptor_service.hpp | 87 +++++++++------
   trunk/boost/asio/detail/reactive_socket_service.hpp | 220 ++++++++++++++++++++++-----------------
   trunk/boost/asio/detail/reactor_op_queue.hpp | 199 +++++++++++++++++++++++-------------
   trunk/boost/asio/detail/select_reactor.hpp | 53 +++++---
   trunk/boost/asio/detail/win_iocp_socket_service.hpp | 56 +++++----
   trunk/boost/asio/detail/wrapped_handler.hpp | 48 +++++--
   10 files changed, 572 insertions(+), 353 deletions(-)

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 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -142,9 +142,18 @@
       return;
 
     if (allow_speculative_read)
+ {
       if (!read_op_queue_.has_operation(descriptor))
- if (handler(boost::system::error_code()))
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
           return;
+ }
+ }
+ }
 
     if (read_op_queue_.enqueue_operation(descriptor, handler))
     {
@@ -170,9 +179,18 @@
       return;
 
     if (allow_speculative_write)
+ {
       if (!write_op_queue_.has_operation(descriptor))
- if (handler(boost::system::error_code()))
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
           return;
+ }
+ }
+ }
 
     if (write_op_queue_.enqueue_operation(descriptor, handler))
     {
@@ -313,16 +331,16 @@
 
     // Dispatch any operation cancellations that were made while the select
     // loop was not running.
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
       timer_queues_[i]->dispatch_cancellations();
 
     // Check if the thread is supposed to stop.
     if (stop_thread_)
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -331,7 +349,7 @@
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
         && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -347,9 +365,9 @@
         int descriptor = pending_event_changes_[i].fd;
         boost::system::error_code ec = boost::system::error_code(
             errno, boost::asio::error::get_system_category());
- read_op_queue_.dispatch_all_operations(descriptor, ec);
- write_op_queue_.dispatch_all_operations(descriptor, ec);
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
     pending_event_changes_.clear();
@@ -370,7 +388,7 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while dispatching operations.
+ // Block signals while performing operations.
     boost::asio::detail::signal_blocker sb;
 
     // Dispatch the waiting events.
@@ -391,17 +409,17 @@
         // Exception operations must be processed first to ensure that any
         // out-of-band data is read before normal data.
         if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
- more_except = except_op_queue_.dispatch_operation(descriptor, ec);
+ more_except = except_op_queue_.perform_operation(descriptor, ec);
         else
           more_except = except_op_queue_.has_operation(descriptor);
 
         if (events[i].events & (POLLIN | POLLERR | POLLHUP))
- more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
+ more_reads = read_op_queue_.perform_operation(descriptor, ec);
         else
           more_reads = read_op_queue_.has_operation(descriptor);
 
         if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
- more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
+ more_writes = write_op_queue_.perform_operation(descriptor, ec);
         else
           more_writes = write_op_queue_.has_operation(descriptor);
 
@@ -436,16 +454,16 @@
           {
             ec = boost::system::error_code(errno,
                 boost::asio::error::get_system_category());
- read_op_queue_.dispatch_all_operations(descriptor, ec);
- write_op_queue_.dispatch_all_operations(descriptor, ec);
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
           }
         }
       }
     }
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
       timer_queues_[i]->dispatch_timers();
@@ -457,7 +475,7 @@
       cancel_ops_unlocked(pending_cancellations_[i]);
     pending_cancellations_.clear();
 
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
   }
 
   // Run the select loop in the thread.
@@ -557,14 +575,14 @@
   // destructors may make calls back into this reactor. We make a copy of the
   // vector of timer queues since the original may be modified while the lock
   // is not held.
- void cleanup_operations_and_timers(
+ void complete_operations_and_cleanup_timers(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     timer_queues_for_cleanup_ = timer_queues_;
     lock.unlock();
- read_op_queue_.cleanup_operations();
- write_op_queue_.cleanup_operations();
- except_op_queue_.cleanup_operations();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
     for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
       timer_queues_for_cleanup_[i]->cleanup_timers();
   }

Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -152,8 +152,13 @@
   {
     if (allow_speculative_read && descriptor_data.allow_speculative_read)
     {
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
 
       // We only get one shot at a speculative read in this function.
       allow_speculative_read = false;
@@ -171,8 +176,13 @@
       // Speculative reads are ok as there are no queued read operations.
       descriptor_data.allow_speculative_read = true;
 
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
     }
 
     // Speculative reads are not ok as there will be queued read operations.
@@ -195,7 +205,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- read_op_queue_.dispatch_all_operations(descriptor, ec);
+ read_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -209,8 +219,13 @@
   {
     if (allow_speculative_write && descriptor_data.allow_speculative_write)
     {
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
 
       // We only get one shot at a speculative write in this function.
       allow_speculative_write = false;
@@ -228,8 +243,13 @@
       // Speculative writes are ok as there are no queued write operations.
       descriptor_data.allow_speculative_write = true;
 
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
     }
 
     // Speculative writes are not ok as there will be queued write operations.
@@ -252,7 +272,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -285,7 +305,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -322,7 +342,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -407,16 +427,16 @@
 
     // Dispatch any operation cancellations that were made while the select
     // loop was not running.
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
       timer_queues_[i]->dispatch_cancellations();
 
     // Check if the thread is supposed to stop.
     if (stop_thread_)
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -425,7 +445,7 @@
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
         && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -442,7 +462,7 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while dispatching operations.
+ // Block signals while performing operations.
     boost::asio::detail::signal_blocker sb;
 
     // Dispatch the waiting events.
@@ -463,17 +483,17 @@
         // Exception operations must be processed first to ensure that any
         // out-of-band data is read before normal data.
         if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP))
- more_except = except_op_queue_.dispatch_operation(descriptor, ec);
+ more_except = except_op_queue_.perform_operation(descriptor, ec);
         else
           more_except = except_op_queue_.has_operation(descriptor);
 
         if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP))
- more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
+ more_reads = read_op_queue_.perform_operation(descriptor, ec);
         else
           more_reads = read_op_queue_.has_operation(descriptor);
 
         if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
- more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
+ more_writes = write_op_queue_.perform_operation(descriptor, ec);
         else
           more_writes = write_op_queue_.has_operation(descriptor);
 
@@ -507,16 +527,16 @@
           {
             ec = boost::system::error_code(errno,
                 boost::asio::error::get_system_category());
- read_op_queue_.dispatch_all_operations(descriptor, ec);
- write_op_queue_.dispatch_all_operations(descriptor, ec);
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
           }
         }
       }
     }
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
       timer_queues_[i]->dispatch_timers();
@@ -532,7 +552,7 @@
     need_epoll_wait_ = !read_op_queue_.empty()
       || !write_op_queue_.empty() || !except_op_queue_.empty();
 
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
   }
 
   // Run the select loop in the thread.
@@ -635,14 +655,14 @@
   // destructors may make calls back into this reactor. We make a copy of the
   // vector of timer queues since the original may be modified while the lock
   // is not held.
- void cleanup_operations_and_timers(
+ void complete_operations_and_cleanup_timers(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     timer_queues_for_cleanup_ = timer_queues_;
     lock.unlock();
- read_op_queue_.cleanup_operations();
- write_op_queue_.cleanup_operations();
- except_op_queue_.cleanup_operations();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
     for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
       timer_queues_for_cleanup_[i]->cleanup_timers();
   }

Added: trunk/boost/asio/detail/handler_base_from_member.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/handler_base_from_member.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -0,0 +1,78 @@
+//
+// handler_base_from_member.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 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_HANDLER_BASE_FROM_MEMBER_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Base class for classes that need a handler data member. Forwards the custom
+// allocation and invocation hooks to the contained handler.
+template <typename Handler>
+class handler_base_from_member
+{
+public:
+ handler_base_from_member(Handler handler)
+ : handler_(handler)
+ {
+ }
+
+//protected:
+ Handler handler_;
+
+protected:
+ // Protected destructor to prevent deletion through this type.
+ ~handler_base_from_member()
+ {
+ }
+};
+
+template <typename Handler>
+inline void* asio_handler_allocate(std::size_t size,
+ handler_base_from_member<Handler>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ handler_base_from_member<Handler>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler>
+inline void asio_handler_invoke(const Function& function,
+ handler_base_from_member<Handler>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP

Modified: trunk/boost/asio/detail/hash_map.hpp
==============================================================================
--- trunk/boost/asio/detail/hash_map.hpp (original)
+++ trunk/boost/asio/detail/hash_map.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -44,6 +44,7 @@
 }
 #endif // defined(_WIN64)
 
+// Note: assumes K and V are POD types.
 template <typename K, typename V>
 class hash_map
   : private noncopyable
@@ -140,7 +141,7 @@
     if (it == values_.end())
     {
       buckets_[bucket].first = buckets_[bucket].last =
- values_.insert(values_.end(), v);
+ values_insert(values_.end(), v);
       return std::pair<iterator, bool>(buckets_[bucket].last, true);
     }
     iterator end = buckets_[bucket].last;
@@ -151,7 +152,7 @@
         return std::pair<iterator, bool>(it, false);
       ++it;
     }
- buckets_[bucket].last = values_.insert(end, v);
+ buckets_[bucket].last = values_insert(end, v);
     return std::pair<iterator, bool>(buckets_[bucket].last, true);
   }
 
@@ -170,7 +171,7 @@
     else if (is_last)
       --buckets_[bucket].last;
 
- values_.erase(it);
+ values_erase(it);
   }
 
   // Remove all entries from the map.
@@ -185,9 +186,36 @@
   }
 
 private:
+ // Insert an element into the values list by splicing from the spares list,
+ // if a spare is available, and otherwise by inserting a new element.
+ iterator values_insert(iterator it, const value_type& v)
+ {
+ if (spares_.empty())
+ {
+ return values_.insert(it, v);
+ }
+ else
+ {
+ spares_.front() = v;
+ values_.splice(it, spares_, spares_.begin());
+ return --it;
+ }
+ }
+
+ // Erase an element from the values list by splicing it to the spares list.
+ void values_erase(iterator it)
+ {
+ *it = value_type();
+ spares_.splice(spares_.begin(), values_, it);
+ }
+
   // The list of all values in the hash map.
   std::list<value_type> values_;
 
+ // The list of spare nodes waiting to be recycled. Assumes that POD types only
+ // are stored in the hash map.
+ std::list<value_type> spares_;
+
   // The type for a bucket in the hash table.
   struct bucket_type
   {

Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -151,8 +151,13 @@
   {
     if (allow_speculative_read && descriptor_data.allow_speculative_read)
     {
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
 
       // We only get one shot at a speculative read in this function.
       allow_speculative_read = false;
@@ -170,8 +175,13 @@
       // Speculative reads are ok as there are no queued read operations.
       descriptor_data.allow_speculative_read = true;
 
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
     }
 
     // Speculative reads are not ok as there will be queued read operations.
@@ -185,7 +195,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- read_op_queue_.dispatch_all_operations(descriptor, ec);
+ read_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -199,8 +209,13 @@
   {
     if (allow_speculative_write && descriptor_data.allow_speculative_write)
     {
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
 
       // We only get one shot at a speculative write in this function.
       allow_speculative_write = false;
@@ -218,8 +233,13 @@
       // Speculative writes are ok as there are no queued write operations.
       descriptor_data.allow_speculative_write = true;
 
- if (handler(boost::system::error_code()))
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
         return;
+ }
     }
 
     // Speculative writes are not ok as there will be queued write operations.
@@ -233,7 +253,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -260,7 +280,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -287,7 +307,7 @@
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
       }
     }
   }
@@ -374,16 +394,16 @@
 
     // Dispatch any operation cancellations that were made while the select
     // loop was not running.
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
       timer_queues_[i]->dispatch_cancellations();
 
     // Check if the thread is supposed to stop.
     if (stop_thread_)
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -392,7 +412,7 @@
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
         && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -412,7 +432,7 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while dispatching operations.
+ // Block signals while performing operations.
     boost::asio::detail::signal_blocker sb;
 
     // Dispatch the waiting events.
@@ -432,22 +452,22 @@
         {
           boost::system::error_code error(
               events[i].data, boost::asio::error::get_system_category());
- except_op_queue_.dispatch_all_operations(descriptor, error);
- read_op_queue_.dispatch_all_operations(descriptor, error);
+ except_op_queue_.perform_all_operations(descriptor, error);
+ read_op_queue_.perform_all_operations(descriptor, error);
         }
         else if (events[i].flags & EV_OOBAND)
         {
           boost::system::error_code error;
- more_except = except_op_queue_.dispatch_operation(descriptor, error);
+ more_except = except_op_queue_.perform_operation(descriptor, error);
           if (events[i].data > 0)
- more_reads = read_op_queue_.dispatch_operation(descriptor, error);
+ more_reads = read_op_queue_.perform_operation(descriptor, error);
           else
             more_reads = read_op_queue_.has_operation(descriptor);
         }
         else
         {
           boost::system::error_code error;
- more_reads = read_op_queue_.dispatch_operation(descriptor, error);
+ more_reads = read_op_queue_.perform_operation(descriptor, error);
           more_except = except_op_queue_.has_operation(descriptor);
         }
 
@@ -463,8 +483,8 @@
         {
           boost::system::error_code error(errno,
               boost::asio::error::get_system_category());
- except_op_queue_.dispatch_all_operations(descriptor, error);
- read_op_queue_.dispatch_all_operations(descriptor, error);
+ except_op_queue_.perform_all_operations(descriptor, error);
+ read_op_queue_.perform_all_operations(descriptor, error);
         }
       }
       else if (events[i].filter == EVFILT_WRITE)
@@ -475,12 +495,12 @@
         {
           boost::system::error_code error(
               events[i].data, boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, error);
+ write_op_queue_.perform_all_operations(descriptor, error);
         }
         else
         {
           boost::system::error_code error;
- more_writes = write_op_queue_.dispatch_operation(descriptor, error);
+ more_writes = write_op_queue_.perform_operation(descriptor, error);
         }
 
         // Update the descriptor in the kqueue.
@@ -493,14 +513,14 @@
         {
           boost::system::error_code error(errno,
               boost::asio::error::get_system_category());
- write_op_queue_.dispatch_all_operations(descriptor, error);
+ write_op_queue_.perform_all_operations(descriptor, error);
         }
       }
     }
 
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
       timer_queues_[i]->dispatch_timers();
@@ -516,7 +536,7 @@
     need_kqueue_wait_ = !read_op_queue_.empty()
       || !write_op_queue_.empty() || !except_op_queue_.empty();
 
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
   }
 
   // Run the select loop in the thread.
@@ -617,14 +637,14 @@
   // destructors may make calls back into this reactor. We make a copy of the
   // vector of timer queues since the original may be modified while the lock
   // is not held.
- void cleanup_operations_and_timers(
+ void complete_operations_and_cleanup_timers(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     timer_queues_for_cleanup_ = timer_queues_;
     lock.unlock();
- read_op_queue_.cleanup_operations();
- write_op_queue_.cleanup_operations();
- except_op_queue_.cleanup_operations();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
     for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
       timer_queues_for_cleanup_[i]->cleanup_timers();
   }

Modified: trunk/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_descriptor_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_descriptor_service.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -21,6 +21,7 @@
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/descriptor_ops.hpp>
@@ -309,25 +310,27 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class write_handler
+ class write_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- write_handler(int descriptor, boost::asio::io_service& io_service,
+ write_operation(int descriptor, boost::asio::io_service& io_service,
         const ConstBufferSequence& buffers, Handler handler)
- : descriptor_(descriptor),
+ : handler_base_from_member<Handler>(handler),
+ descriptor_(descriptor),
         io_service_(io_service),
         work_(io_service),
- buffers_(buffers),
- handler_(handler)
+ buffers_(buffers)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -345,7 +348,6 @@
       }
 
       // Write the data.
- boost::system::error_code ec;
       int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec);
 
       // Check if we need to run the operation again.
@@ -353,16 +355,21 @@
           || ec == boost::asio::error::try_again)
         return false;
 
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     int descriptor_;
     boost::asio::io_service& io_service_;
     boost::asio::io_service::work work_;
     ConstBufferSequence buffers_;
- Handler handler_;
   };
 
   // Start an asynchronous write. The data being sent must be valid for the
@@ -411,30 +418,38 @@
       }
 
       reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
- write_handler<ConstBufferSequence, Handler>(
+ write_operation<ConstBufferSequence, Handler>(
             impl.descriptor_, this->get_io_service(), buffers, handler));
     }
   }
 
   template <typename Handler>
- class null_buffers_handler
+ class null_buffers_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- null_buffers_handler(boost::asio::io_service& io_service, Handler handler)
- : work_(io_service),
- handler_(handler)
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ work_(io_service)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
     {
- work_.get_io_service().post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ this->handler_, ec, bytes_transferred));
+ }
+
   private:
     boost::asio::io_service::work work_;
- Handler handler_;
   };
 
   // Start an asynchronous wait until data can be written without blocking.
@@ -450,7 +465,7 @@
     else
     {
       reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -547,25 +562,27 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class read_handler
+ class read_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- read_handler(int descriptor, boost::asio::io_service& io_service,
+ read_operation(int descriptor, boost::asio::io_service& io_service,
         const MutableBufferSequence& buffers, Handler handler)
- : descriptor_(descriptor),
+ : handler_base_from_member<Handler>(handler),
+ descriptor_(descriptor),
         io_service_(io_service),
         work_(io_service),
- buffers_(buffers),
- handler_(handler)
+ buffers_(buffers)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -583,7 +600,6 @@
       }
 
       // Read some data.
- boost::system::error_code ec;
       int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec);
       if (bytes == 0)
         ec = boost::asio::error::eof;
@@ -593,16 +609,21 @@
           || ec == boost::asio::error::try_again)
         return false;
 
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     int descriptor_;
     boost::asio::io_service& io_service_;
     boost::asio::io_service::work work_;
     MutableBufferSequence buffers_;
- Handler handler_;
   };
 
   // Start an asynchronous read. The buffer for the data being read must be
@@ -651,7 +672,7 @@
       }
 
       reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
- read_handler<MutableBufferSequence, Handler>(
+ read_operation<MutableBufferSequence, Handler>(
             impl.descriptor_, this->get_io_service(), buffers, handler));
     }
   }
@@ -669,7 +690,7 @@
     else
     {
       reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }

Modified: trunk/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -26,6 +26,7 @@
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/socket_base.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/socket_holder.hpp>
@@ -580,27 +581,29 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class send_handler
+ class send_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- send_handler(socket_type socket, boost::asio::io_service& io_service,
+ send_operation(socket_type socket, boost::asio::io_service& io_service,
         const ConstBufferSequence& buffers, socket_base::message_flags flags,
         Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
         work_(io_service),
         buffers_(buffers),
- flags_(flags),
- handler_(handler)
+ flags_(flags)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -618,7 +621,6 @@
       }
 
       // Send the data.
- boost::system::error_code ec;
       int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
 
       // Check if we need to run the operation again.
@@ -626,17 +628,22 @@
           || ec == boost::asio::error::try_again)
         return false;
 
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
     boost::asio::io_service::work work_;
     ConstBufferSequence buffers_;
     socket_base::message_flags flags_;
- Handler handler_;
   };
 
   // Start an asynchronous send. The data being sent must be valid for the
@@ -688,30 +695,38 @@
       }
 
       reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- send_handler<ConstBufferSequence, Handler>(
+ send_operation<ConstBufferSequence, Handler>(
             impl.socket_, this->get_io_service(), buffers, flags, handler));
     }
   }
 
   template <typename Handler>
- class null_buffers_handler
+ class null_buffers_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- null_buffers_handler(boost::asio::io_service& io_service, Handler handler)
- : work_(io_service),
- handler_(handler)
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ work_(io_service)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
     {
- work_.get_io_service().post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ this->handler_, ec, bytes_transferred));
+ }
+
   private:
     boost::asio::io_service::work work_;
- Handler handler_;
   };
 
   // Start an asynchronous wait until data can be sent without blocking.
@@ -727,7 +742,7 @@
     else
     {
       reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -811,28 +826,30 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class send_to_handler
+ class send_to_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- send_to_handler(socket_type socket, boost::asio::io_service& io_service,
+ send_to_operation(socket_type socket, boost::asio::io_service& io_service,
         const ConstBufferSequence& buffers, const endpoint_type& endpoint,
         socket_base::message_flags flags, Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
         work_(io_service),
         buffers_(buffers),
         destination_(endpoint),
- flags_(flags),
- handler_(handler)
+ flags_(flags)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -850,7 +867,6 @@
       }
 
       // Send the data.
- boost::system::error_code ec;
       int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
           destination_.data(), destination_.size(), ec);
 
@@ -859,10 +875,16 @@
           || ec == boost::asio::error::try_again)
         return false;
 
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
@@ -870,7 +892,6 @@
     ConstBufferSequence buffers_;
     endpoint_type destination_;
     socket_base::message_flags flags_;
- Handler handler_;
   };
 
   // Start an asynchronous send. The data being sent must be valid for the
@@ -902,7 +923,7 @@
       }
 
       reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- send_to_handler<ConstBufferSequence, Handler>(
+ send_to_operation<ConstBufferSequence, Handler>(
             impl.socket_, this->get_io_service(), buffers,
             destination, flags, handler));
     }
@@ -921,7 +942,7 @@
     else
     {
       reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -1018,27 +1039,29 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class receive_handler
+ class receive_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- receive_handler(socket_type socket, boost::asio::io_service& io_service,
+ receive_operation(socket_type socket, boost::asio::io_service& io_service,
         const MutableBufferSequence& buffers, socket_base::message_flags flags,
         Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
         work_(io_service),
         buffers_(buffers),
- flags_(flags),
- handler_(handler)
+ flags_(flags)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -1056,7 +1079,6 @@
       }
 
       // Receive some data.
- boost::system::error_code ec;
       int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
       if (bytes == 0)
         ec = boost::asio::error::eof;
@@ -1066,17 +1088,22 @@
           || ec == boost::asio::error::try_again)
         return false;
 
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
     boost::asio::io_service::work work_;
     MutableBufferSequence buffers_;
     socket_base::message_flags flags_;
- Handler handler_;
   };
 
   // Start an asynchronous receive. The buffer for the data being received
@@ -1131,13 +1158,13 @@
       if (flags & socket_base::message_out_of_band)
       {
         reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- receive_handler<MutableBufferSequence, Handler>(
+ receive_operation<MutableBufferSequence, Handler>(
               impl.socket_, this->get_io_service(), buffers, flags, handler));
       }
       else
       {
         reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- receive_handler<MutableBufferSequence, Handler>(
+ receive_operation<MutableBufferSequence, Handler>(
               impl.socket_, this->get_io_service(), buffers, flags, handler));
       }
     }
@@ -1156,12 +1183,12 @@
     else if (flags & socket_base::message_out_of_band)
     {
       reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler));
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
     }
     else
     {
       reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -1260,29 +1287,31 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class receive_from_handler
+ class receive_from_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- receive_from_handler(socket_type socket,
+ receive_from_operation(socket_type socket,
         boost::asio::io_service& io_service,
         const MutableBufferSequence& buffers, endpoint_type& endpoint,
         socket_base::message_flags flags, Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
         work_(io_service),
         buffers_(buffers),
         sender_endpoint_(endpoint),
- flags_(flags),
- handler_(handler)
+ flags_(flags)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
+ if (ec)
       {
- io_service_.post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
         return true;
       }
 
@@ -1301,7 +1330,6 @@
 
       // Receive some data.
       std::size_t addr_len = sender_endpoint_.capacity();
- boost::system::error_code ec;
       int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
           sender_endpoint_.data(), &addr_len, ec);
       if (bytes == 0)
@@ -1313,10 +1341,16 @@
         return false;
 
       sender_endpoint_.resize(addr_len);
- io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
@@ -1324,7 +1358,6 @@
     MutableBufferSequence buffers_;
     endpoint_type& sender_endpoint_;
     socket_base::message_flags flags_;
- Handler handler_;
   };
 
   // Start an asynchronous receive. The buffer for the data being received and
@@ -1356,7 +1389,7 @@
       }
 
       reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- receive_from_handler<MutableBufferSequence, Handler>(
+ receive_from_operation<MutableBufferSequence, Handler>(
             impl.socket_, this->get_io_service(), buffers,
             sender_endpoint, flags, handler));
     }
@@ -1381,12 +1414,12 @@
       if (flags & socket_base::message_out_of_band)
       {
         reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler));
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
       }
       else
       {
         reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
             false);
       }
     }
@@ -1483,35 +1516,32 @@
   }
 
   template <typename Socket, typename Handler>
- class accept_handler
+ class accept_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- accept_handler(socket_type socket, boost::asio::io_service& io_service,
+ accept_operation(socket_type socket, boost::asio::io_service& io_service,
         Socket& peer, const protocol_type& protocol,
         endpoint_type* peer_endpoint, bool enable_connection_aborted,
         Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
         work_(io_service),
         peer_(peer),
         protocol_(protocol),
         peer_endpoint_(peer_endpoint),
- enable_connection_aborted_(enable_connection_aborted),
- handler_(handler)
+ enable_connection_aborted_(enable_connection_aborted)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec, std::size_t&)
     {
       // Check whether the operation was successful.
- if (result)
- {
- io_service_.post(bind_handler(handler_, result));
+ if (ec)
         return true;
- }
 
       // Accept the waiting connection.
- boost::system::error_code ec;
       socket_holder new_socket;
       std::size_t addr_len = 0;
       if (peer_endpoint_)
@@ -1547,10 +1577,14 @@
           new_socket.release();
       }
 
- io_service_.post(bind_handler(handler_, ec));
       return true;
     }
 
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(this->handler_, ec));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
@@ -1559,7 +1593,6 @@
     protocol_type protocol_;
     endpoint_type* peer_endpoint_;
     bool enable_connection_aborted_;
- Handler handler_;
   };
 
   // Start an asynchronous accept. The peer and peer_endpoint objects
@@ -1594,7 +1627,7 @@
       }
 
       reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- accept_handler<Socket, Handler>(
+ accept_operation<Socket, Handler>(
             impl.socket_, this->get_io_service(),
             peer, impl.protocol_, peer_endpoint,
             (impl.flags_ & implementation_type::enable_connection_aborted) != 0,
@@ -1628,57 +1661,52 @@
   }
 
   template <typename Handler>
- class connect_handler
+ class connect_operation :
+ public handler_base_from_member<Handler>
   {
   public:
- connect_handler(socket_type socket,
+ connect_operation(socket_type socket,
         boost::asio::io_service& io_service, Handler handler)
- : socket_(socket),
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
         io_service_(io_service),
- work_(io_service),
- handler_(handler)
+ work_(io_service)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec, std::size_t&)
     {
       // Check whether the operation was successful.
- if (result)
- {
- io_service_.post(bind_handler(handler_, result));
+ if (ec)
         return true;
- }
 
       // Get the error code from the connect operation.
       int connect_error = 0;
       size_t connect_error_len = sizeof(connect_error);
- boost::system::error_code ec;
       if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
             &connect_error, &connect_error_len, ec) == socket_error_retval)
- {
- io_service_.post(bind_handler(handler_, ec));
         return true;
- }
 
- // If connection failed then post the handler with the error code.
+ // The connection failed so the handler will be posted with an error code.
       if (connect_error)
       {
         ec = boost::system::error_code(connect_error,
             boost::asio::error::get_system_category());
- io_service_.post(bind_handler(handler_, ec));
         return true;
       }
 
- // Post the result of the successful connection operation.
- io_service_.post(bind_handler(handler_, ec));
       return true;
     }
 
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(this->handler_, ec));
+ }
+
   private:
     socket_type socket_;
     boost::asio::io_service& io_service_;
     boost::asio::io_service::work work_;
- Handler handler_;
   };
 
   // Start an asynchronous connect.
@@ -1723,7 +1751,7 @@
       // The connection is happening in the background, and we need to wait
       // until the socket becomes writeable.
       reactor_.start_connect_op(impl.socket_, impl.reactor_data_,
- connect_handler<Handler>(impl.socket_,
+ connect_operation<Handler>(impl.socket_,
             this->get_io_service(), handler));
     }
     else

Modified: trunk/boost/asio/detail/reactor_op_queue.hpp
==============================================================================
--- trunk/boost/asio/detail/reactor_op_queue.hpp (original)
+++ trunk/boost/asio/detail/reactor_op_queue.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -22,6 +22,7 @@
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/error.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/hash_map.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
 
@@ -38,36 +39,42 @@
   reactor_op_queue()
     : operations_(),
       cancelled_operations_(0),
- cleanup_operations_(0)
+ complete_operations_(0)
   {
   }
 
   // Add a new operation to the queue. Returns true if this is the only
   // operation for the given descriptor, in which case the reactor's event
   // demultiplexing function call may need to be interrupted and restarted.
- template <typename Handler>
- bool enqueue_operation(Descriptor descriptor, Handler handler)
+ template <typename Operation>
+ bool enqueue_operation(Descriptor descriptor, Operation operation)
   {
- op_base* new_op = new op<Handler>(descriptor, handler);
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_alloc_traits<Operation, op<Operation> > alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(operation);
+ handler_ptr<alloc_traits> ptr(raw_ptr, descriptor, operation);
 
     typedef typename operation_map::iterator iterator;
     typedef typename operation_map::value_type value_type;
     std::pair<iterator, bool> entry =
- operations_.insert(value_type(descriptor, new_op));
+ operations_.insert(value_type(descriptor, ptr.get()));
     if (entry.second)
+ {
+ ptr.release();
       return true;
+ }
 
     op_base* current_op = entry.first->second;
     while (current_op->next_)
       current_op = current_op->next_;
- current_op->next_ = new_op;
+ current_op->next_ = ptr.release();
 
     return false;
   }
 
   // Cancel all operations associated with the descriptor. Any operations
   // pending for the descriptor will be notified that they have been cancelled
- // next time dispatch_cancellations is called. Returns true if any operations
+ // next time perform_cancellations is called. Returns true if any operations
   // were cancelled, in which case the reactor's event demultiplexing function
   // may need to be interrupted and restarted.
   bool cancel_operations(Descriptor descriptor)
@@ -99,9 +106,9 @@
     return operations_.find(descriptor) != operations_.end();
   }
 
- // Dispatch the first operation corresponding to the descriptor. Returns true
+ // Perform the first operation corresponding to the descriptor. Returns true
   // if there are more operations queued for the descriptor.
- bool dispatch_operation(Descriptor descriptor,
+ bool perform_operation(Descriptor descriptor,
       const boost::system::error_code& result)
   {
     typename operation_map::iterator i = operations_.find(descriptor);
@@ -109,9 +116,9 @@
     {
       op_base* this_op = i->second;
       i->second = this_op->next_;
- this_op->next_ = cleanup_operations_;
- cleanup_operations_ = this_op;
- bool done = this_op->invoke(result);
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
       if (done)
       {
         // Operation has finished.
@@ -128,8 +135,8 @@
       else
       {
         // Operation wants to be called again. Leave it at the front of the
- // queue for this descriptor, and remove from the cleanup list.
- cleanup_operations_ = this_op->next_;
+ // queue for this descriptor, and remove from the completed list.
+ complete_operations_ = this_op->next_;
         this_op->next_ = i->second;
         i->second = this_op;
         return true;
@@ -138,8 +145,8 @@
     return false;
   }
 
- // Dispatch all operations corresponding to the descriptor.
- void dispatch_all_operations(Descriptor descriptor,
+ // Perform all operations corresponding to the descriptor.
+ void perform_all_operations(Descriptor descriptor,
       const boost::system::error_code& result)
   {
     typename operation_map::iterator i = operations_.find(descriptor);
@@ -149,14 +156,14 @@
       {
         op_base* this_op = i->second;
         i->second = this_op->next_;
- this_op->next_ = cleanup_operations_;
- cleanup_operations_ = this_op;
- bool done = this_op->invoke(result);
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
         if (!done)
         {
           // Operation has not finished yet, so leave at front of queue, and
- // remove from the cleanup list.
- cleanup_operations_ = this_op->next_;
+ // remove from the completed list.
+ complete_operations_ = this_op->next_;
           this_op->next_ = i->second;
           i->second = this_op;
           return;
@@ -179,15 +186,15 @@
       if (!descriptors.set(descriptor))
       {
         boost::system::error_code ec(error::fd_set_failure);
- dispatch_all_operations(descriptor, ec);
+ perform_all_operations(descriptor, ec);
       }
     }
   }
 
- // Dispatch the operations corresponding to the ready file descriptors
+ // Perform the operations corresponding to the ready file descriptors
   // contained in the given descriptor set.
   template <typename Descriptor_Set>
- void dispatch_descriptors(const Descriptor_Set& descriptors,
+ void perform_operations_for_descriptors(const Descriptor_Set& descriptors,
       const boost::system::error_code& result)
   {
     typename operation_map::iterator i = operations_.begin();
@@ -198,9 +205,9 @@
       {
         op_base* this_op = op_iter->second;
         op_iter->second = this_op->next_;
- this_op->next_ = cleanup_operations_;
- cleanup_operations_ = this_op;
- bool done = this_op->invoke(result);
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
         if (done)
         {
           if (!op_iter->second)
@@ -209,8 +216,8 @@
         else
         {
           // Operation has not finished yet, so leave at front of queue, and
- // remove from the cleanup list.
- cleanup_operations_ = this_op->next_;
+ // remove from the completed list.
+ complete_operations_ = this_op->next_;
           this_op->next_ = op_iter->second;
           op_iter->second = this_op;
         }
@@ -218,28 +225,28 @@
     }
   }
 
- // Dispatch any pending cancels for operations.
- void dispatch_cancellations()
+ // Perform any pending cancels for operations.
+ void perform_cancellations()
   {
     while (cancelled_operations_)
     {
       op_base* this_op = cancelled_operations_;
       cancelled_operations_ = this_op->next_;
- this_op->next_ = cleanup_operations_;
- cleanup_operations_ = this_op;
- this_op->invoke(boost::asio::error::operation_aborted);
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ this_op->perform(boost::asio::error::operation_aborted);
     }
   }
 
- // Destroy operations that are waiting to be cleaned up.
- void cleanup_operations()
+ // Complete all operations that are waiting to be completed.
+ void complete_operations()
   {
- while (cleanup_operations_)
+ while (complete_operations_)
     {
- op_base* next_op = cleanup_operations_->next_;
- cleanup_operations_->next_ = 0;
- cleanup_operations_->destroy();
- cleanup_operations_ = next_op;
+ op_base* next_op = complete_operations_->next_;
+ complete_operations_->next_ = 0;
+ complete_operations_->complete();
+ complete_operations_ = next_op;
     }
   }
 
@@ -254,12 +261,12 @@
       cancelled_operations_ = next_op;
     }
 
- while (cleanup_operations_)
+ while (complete_operations_)
     {
- op_base* next_op = cleanup_operations_->next_;
- cleanup_operations_->next_ = 0;
- cleanup_operations_->destroy();
- cleanup_operations_ = next_op;
+ op_base* next_op = complete_operations_->next_;
+ complete_operations_->next_ = 0;
+ complete_operations_->destroy();
+ complete_operations_ = next_op;
     }
 
     typename operation_map::iterator i = operations_.begin();
@@ -291,28 +298,40 @@
     }
 
     // Perform the operation.
- bool invoke(const boost::system::error_code& result)
+ bool perform(const boost::system::error_code& result)
+ {
+ result_ = result;
+ return perform_func_(this, result_, bytes_transferred_);
+ }
+
+ // Destroy the operation and post the handler.
+ void complete()
     {
- return invoke_func_(this, result);
+ complete_func_(this, result_, bytes_transferred_);
     }
 
     // Destroy the operation.
     void destroy()
     {
- return destroy_func_(this);
+ destroy_func_(this);
     }
 
   protected:
- typedef bool (*invoke_func_type)(op_base*,
- const boost::system::error_code&);
+ typedef bool (*perform_func_type)(op_base*,
+ boost::system::error_code&, std::size_t&);
+ typedef void (*complete_func_type)(op_base*,
+ const boost::system::error_code&, std::size_t);
     typedef void (*destroy_func_type)(op_base*);
 
     // Construct an operation for the given descriptor.
- op_base(invoke_func_type invoke_func,
+ op_base(perform_func_type perform_func, complete_func_type complete_func,
         destroy_func_type destroy_func, Descriptor descriptor)
- : invoke_func_(invoke_func),
+ : perform_func_(perform_func),
+ complete_func_(complete_func),
         destroy_func_(destroy_func),
         descriptor_(descriptor),
+ result_(),
+ bytes_transferred_(0),
         next_(0)
     {
     }
@@ -325,48 +344,84 @@
   private:
     friend class reactor_op_queue<Descriptor>;
 
- // The function to be called to dispatch the handler.
- invoke_func_type invoke_func_;
+ // The function to be called to perform the operation.
+ perform_func_type perform_func_;
+
+ // The function to be called to delete the operation and post the handler.
+ complete_func_type complete_func_;
 
- // The function to be called to delete the handler.
+ // The function to be called to delete the operation.
     destroy_func_type destroy_func_;
 
     // The descriptor associated with the operation.
     Descriptor descriptor_;
 
+ // The result of the operation.
+ boost::system::error_code result_;
+
+ // The number of bytes transferred in the operation.
+ std::size_t bytes_transferred_;
+
     // The next operation for the same file descriptor.
     op_base* next_;
   };
 
- // Adaptor class template for using handlers in operations.
- template <typename Handler>
+ // Adaptor class template for operations.
+ template <typename Operation>
   class op
     : public op_base
   {
   public:
     // Constructor.
- op(Descriptor descriptor, Handler handler)
- : op_base(&op<Handler>::invoke_handler,
- &op<Handler>::destroy_handler, descriptor),
- handler_(handler)
+ op(Descriptor descriptor, Operation operation)
+ : op_base(&op<Operation>::do_perform, &op<Operation>::do_complete,
+ &op<Operation>::do_destroy, descriptor),
+ operation_(operation)
     {
     }
 
- // Invoke the handler.
- static bool invoke_handler(op_base* base,
- const boost::system::error_code& result)
+ // Perform the operation.
+ static bool do_perform(op_base* base,
+ boost::system::error_code& result, std::size_t& bytes_transferred)
+ {
+ return static_cast<op<Operation>*>(base)->operation_.perform(
+ result, bytes_transferred);
+ }
+
+ // Destroy the operation and post the handler.
+ static void do_complete(op_base* base,
+ const boost::system::error_code& result, std::size_t bytes_transferred)
     {
- return static_cast<op<Handler>*>(base)->handler_(result);
+ // Take ownership of the operation object.
+ typedef op<Operation> this_type;
+ this_type* this_op(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Operation, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_op->operation_, this_op);
+
+ // Make a copy of the error_code and the operation so that the memory can
+ // be deallocated before the upcall is made.
+ boost::system::error_code ec(result);
+ Operation operation(this_op->operation_);
+
+ // Free the memory associated with the operation.
+ ptr.reset();
+
+ // Make the upcall.
+ operation.complete(ec, bytes_transferred);
     }
 
- // Delete the handler.
- static void destroy_handler(op_base* base)
+ // Destroy the operation.
+ static void do_destroy(op_base* base)
     {
- delete static_cast<op<Handler>*>(base);
+ // Take ownership of the operation object.
+ typedef op<Operation> this_type;
+ this_type* this_op(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Operation, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_op->operation_, this_op);
     }
 
   private:
- Handler handler_;
+ Operation operation_;
   };
 
   // The type for a map of operations.
@@ -378,8 +433,8 @@
   // The list of operations that have been cancelled.
   op_base* cancelled_operations_;
 
- // The list of operations to be destroyed.
- op_base* cleanup_operations_;
+ // The list of operations waiting to be completed.
+ op_base* complete_operations_;
 };
 
 } // namespace detail

Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -171,19 +171,30 @@
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether one of the handlers has already been called. If it has,
       // then we don't want to do anything in this handler.
       if (*completed_)
+ {
+ completed_.reset(); // Indicate that this handler should not complete.
         return true;
+ }
 
       // Cancel the other reactor operation for the connection.
       *completed_ = true;
       reactor_.enqueue_cancel_ops_unlocked(descriptor_);
 
       // Call the contained handler.
- return handler_(result);
+ return handler_.perform(ec, bytes_transferred);
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ if (completed_.get())
+ handler_.complete(ec, bytes_transferred);
     }
 
   private:
@@ -300,16 +311,16 @@
 
     // Dispatch any operation cancellations that were made while the select
     // loop was not running.
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
- except_op_queue_.dispatch_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
       timer_queues_[i]->dispatch_cancellations();
 
     // Check if the thread is supposed to stop.
     if (stop_thread_)
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -318,7 +329,7 @@
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
         && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
       return;
     }
 
@@ -360,15 +371,15 @@
     {
       // Exception operations must be processed first to ensure that any
       // out-of-band data is read before normal data.
- except_op_queue_.dispatch_descriptors(except_fds,
- boost::system::error_code());
- read_op_queue_.dispatch_descriptors(read_fds,
- boost::system::error_code());
- write_op_queue_.dispatch_descriptors(write_fds,
- boost::system::error_code());
- except_op_queue_.dispatch_cancellations();
- read_op_queue_.dispatch_cancellations();
- write_op_queue_.dispatch_cancellations();
+ except_op_queue_.perform_operations_for_descriptors(
+ except_fds, boost::system::error_code());
+ read_op_queue_.perform_operations_for_descriptors(
+ read_fds, boost::system::error_code());
+ write_op_queue_.perform_operations_for_descriptors(
+ write_fds, boost::system::error_code());
+ except_op_queue_.perform_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
     }
     for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
@@ -381,7 +392,7 @@
       cancel_ops_unlocked(pending_cancellations_[i]);
     pending_cancellations_.clear();
 
- cleanup_operations_and_timers(lock);
+ complete_operations_and_cleanup_timers(lock);
   }
 
   // Run the select loop in the thread.
@@ -466,14 +477,14 @@
   // destructors may make calls back into this reactor. We make a copy of the
   // vector of timer queues since the original may be modified while the lock
   // is not held.
- void cleanup_operations_and_timers(
+ void complete_operations_and_cleanup_timers(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     timer_queues_for_cleanup_ = timer_queues_;
     lock.unlock();
- read_op_queue_.cleanup_operations();
- write_op_queue_.cleanup_operations();
- except_op_queue_.cleanup_operations();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
     for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
       timer_queues_for_cleanup_[i]->cleanup_timers();
   }

Modified: trunk/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_service.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -885,21 +885,29 @@
   }
 
   template <typename Handler>
- class null_buffers_handler
+ class null_buffers_operation
   {
   public:
- null_buffers_handler(boost::asio::io_service& io_service, Handler handler)
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
       : work_(io_service),
         handler_(handler)
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
     {
- work_.get_io_service().post(bind_handler(handler_, result, 0));
+ bytes_transferred = 0;
       return true;
     }
 
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ handler_, ec, bytes_transferred));
+ }
+
   private:
     boost::asio::io_service::work work_;
     Handler handler_;
@@ -930,7 +938,7 @@
       }
 
       reactor->start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -1157,7 +1165,7 @@
       }
 
       reactor->start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
           false);
     }
   }
@@ -1470,12 +1478,12 @@
       if (flags & socket_base::message_out_of_band)
       {
         reactor->start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler));
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
       }
       else
       {
         reactor->start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
             false);
       }
     }
@@ -1743,12 +1751,12 @@
       if (flags & socket_base::message_out_of_band)
       {
         reactor->start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler));
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
       }
       else
       {
         reactor->start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_handler<Handler>(this->get_io_service(), handler),
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
             false);
       }
     }
@@ -2112,10 +2120,10 @@
   }
 
   template <typename Handler>
- class connect_handler
+ class connect_operation
   {
   public:
- connect_handler(socket_type socket, bool user_set_non_blocking,
+ connect_operation(socket_type socket, bool user_set_non_blocking,
         boost::asio::io_service& io_service, Handler handler)
       : socket_(socket),
         user_set_non_blocking_(user_set_non_blocking),
@@ -2125,32 +2133,25 @@
     {
     }
 
- bool operator()(const boost::system::error_code& result)
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
     {
       // Check whether the operation was successful.
- if (result)
- {
- io_service_.post(bind_handler(handler_, result));
+ if (ec)
         return true;
- }
 
       // Get the error code from the connect operation.
       int connect_error = 0;
       size_t connect_error_len = sizeof(connect_error);
- boost::system::error_code ec;
       if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
             &connect_error, &connect_error_len, ec) == socket_error_retval)
- {
- io_service_.post(bind_handler(handler_, ec));
         return true;
- }
 
       // If connection failed then post the handler with the error code.
       if (connect_error)
       {
         ec = boost::system::error_code(connect_error,
             boost::asio::error::get_system_category());
- io_service_.post(bind_handler(handler_, ec));
         return true;
       }
 
@@ -2159,18 +2160,19 @@
       {
         ioctl_arg_type non_blocking = 0;
         if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec))
- {
- io_service_.post(bind_handler(handler_, ec));
           return true;
- }
       }
 
       // Post the result of the successful connection operation.
       ec = boost::system::error_code();
- io_service_.post(bind_handler(handler_, ec));
       return true;
     }
 
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(handler_, ec));
+ }
+
   private:
     socket_type socket_;
     bool user_set_non_blocking_;
@@ -2243,7 +2245,7 @@
       // until the socket becomes writeable.
       boost::shared_ptr<bool> completed(new bool(false));
       reactor->start_connect_op(impl.socket_, impl.reactor_data_,
- connect_handler<Handler>(
+ connect_operation<Handler>(
             impl.socket_,
             (impl.flags_ & implementation_type::user_set_non_blocking) != 0,
             this->get_io_service(), handler));

Modified: trunk/boost/asio/detail/wrapped_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/wrapped_handler.hpp (original)
+++ trunk/boost/asio/detail/wrapped_handler.hpp 2008-05-05 02:30:13 EDT (Mon, 05 May 2008)
@@ -128,22 +128,6 @@
   Handler handler_;
 };
 
-template <typename Dispatcher, typename Handler>
-inline void* asio_handler_allocate(std::size_t size,
- wrapped_handler<Dispatcher, Handler>* this_handler)
-{
- return boost_asio_handler_alloc_helpers::allocate(
- size, &this_handler->handler_);
-}
-
-template <typename Dispatcher, typename Handler>
-inline void asio_handler_deallocate(void* pointer, std::size_t size,
- wrapped_handler<Dispatcher, Handler>* this_handler)
-{
- boost_asio_handler_alloc_helpers::deallocate(
- pointer, size, &this_handler->handler_);
-}
-
 template <typename Handler, typename Context>
 class rewrapped_handler
 {
@@ -169,6 +153,22 @@
   Context context_;
 };
 
+template <typename Dispatcher, typename Handler>
+inline void* asio_handler_allocate(std::size_t size,
+ wrapped_handler<Dispatcher, Handler>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Dispatcher, typename Handler>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ wrapped_handler<Dispatcher, Handler>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
 template <typename Function, typename Dispatcher, typename Handler>
 inline void asio_handler_invoke(const Function& function,
     wrapped_handler<Dispatcher, Handler>* this_handler)
@@ -178,6 +178,22 @@
         function, this_handler->handler_));
 }
 
+template <typename Handler, typename Context>
+inline void* asio_handler_allocate(std::size_t size,
+ rewrapped_handler<Handler, Context>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->context_);
+}
+
+template <typename Handler, typename Context>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ rewrapped_handler<Handler, Context>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->context_);
+}
+
 template <typename Function, typename Handler, typename Context>
 inline void asio_handler_invoke(const Function& function,
     rewrapped_handler<Handler, Context>* this_handler)


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