Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r60680 - in branches/release: . boost boost/algorithm/string boost/archive boost/asio boost/asio/detail boost/asio/impl boost/asio/ip boost/asio/posix boost/asio/ssl/detail boost/asio/windows boost/bimap boost/detail boost/filesystem boost/functional/hash boost/fusion boost/graph boost/integer boost/interprocess boost/intrusive boost/numeric/ublas boost/program_options boost/property_tree boost/python boost/regex boost/signals boost/signals2 boost/spirit boost/spirit/home boost/spirit/home/karma boost/spirit/home/support boost/statechart boost/system boost/thread boost/tr1 boost/type_traits boost/utility boost/uuid boost/variant boost/wave doc libs libs/array/doc libs/bimap libs/filesystem libs/functional/hash libs/fusion libs/graph_parallel libs/integer libs/interprocess libs/intrusive libs/mpl/doc/refmanual libs/mpl/doc/src/refmanual libs/numeric/ublas libs/numeric/ublas/doc libs/program_options libs/property_tree libs/python libs/regex libs/regex/doc libs/signals libs/signals2 libs/spirit libs/spirit/classic/example libs/spirit/doc libs/spirit/example libs/spirit/phoenix libs/spirit/test libs/spirit/test/qi libs/statechart libs/static_assert libs/system libs/thread libs/thread/doc libs/timer libs/tr1 libs/type_traits libs/utility libs/uuid libs/wave more people status tools tools/bcp tools/boostbook tools/build/v2 tools/inspect tools/regression tools/release tools/wave wiki
From: chris_at_[hidden]
Date: 2010-03-17 20:58:53


Author: chris_kohlhoff
Date: 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
New Revision: 60680
URL: http://svn.boost.org/trac/boost/changeset/60680

Log:
Merge reworked implementation from trunk.

Added:
   branches/release/boost/asio/detail/base_from_completion_cond.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/base_from_completion_cond.hpp
   branches/release/boost/asio/detail/buffer_sequence_adapter.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/buffer_sequence_adapter.hpp
   branches/release/boost/asio/detail/completion_handler.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/completion_handler.hpp
   branches/release/boost/asio/detail/fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/fenced_block.hpp
   branches/release/boost/asio/detail/gcc_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/gcc_fenced_block.hpp
   branches/release/boost/asio/detail/gcc_x86_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/gcc_x86_fenced_block.hpp
   branches/release/boost/asio/detail/macos_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/macos_fenced_block.hpp
   branches/release/boost/asio/detail/null_buffers_op.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/null_buffers_op.hpp
   branches/release/boost/asio/detail/null_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/null_fenced_block.hpp
   branches/release/boost/asio/detail/op_queue.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/op_queue.hpp
   branches/release/boost/asio/detail/operation.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/operation.hpp
   branches/release/boost/asio/detail/reactor.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/reactor.hpp
   branches/release/boost/asio/detail/reactor_fwd.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/reactor_fwd.hpp
   branches/release/boost/asio/detail/reactor_op.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/reactor_op.hpp
   branches/release/boost/asio/detail/solaris_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/solaris_fenced_block.hpp
   branches/release/boost/asio/detail/task_io_service_operation.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/task_io_service_operation.hpp
   branches/release/boost/asio/detail/timer_op.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/timer_op.hpp
   branches/release/boost/asio/detail/timer_queue_fwd.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/timer_queue_fwd.hpp
   branches/release/boost/asio/detail/timer_queue_set.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/timer_queue_set.hpp
   branches/release/boost/asio/detail/timer_scheduler.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/timer_scheduler.hpp
   branches/release/boost/asio/detail/timer_scheduler_fwd.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/timer_scheduler_fwd.hpp
   branches/release/boost/asio/detail/win_fenced_block.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/win_fenced_block.hpp
   branches/release/boost/asio/detail/win_iocp_operation.hpp
      - copied unchanged from r60380, /trunk/boost/asio/detail/win_iocp_operation.hpp
Removed:
   branches/release/boost/asio/detail/const_buffers_iterator.hpp
   branches/release/boost/asio/detail/handler_base_from_member.hpp
   branches/release/boost/asio/detail/handler_queue.hpp
   branches/release/boost/asio/detail/indirect_handler_queue.hpp
   branches/release/boost/asio/detail/task_io_service_2lock.hpp
Properties modified:
   branches/release/ (props changed)
   branches/release/CMakeLists.txt (props changed)
   branches/release/INSTALL (props changed)
   branches/release/Jamroot (props changed)
   branches/release/LICENSE_1_0.txt (props changed)
   branches/release/boost/ (props changed)
   branches/release/boost-build.jam (props changed)
   branches/release/boost.css (props changed)
   branches/release/boost.png (props changed)
   branches/release/boost/algorithm/string/ (props changed)
   branches/release/boost/archive/ (props changed)
   branches/release/boost/array.hpp (props changed)
   branches/release/boost/bimap/ (props changed)
   branches/release/boost/detail/ (props changed)
   branches/release/boost/filesystem/ (props changed)
   branches/release/boost/functional/hash/ (props changed)
   branches/release/boost/fusion/ (props changed)
   branches/release/boost/graph/ (props changed)
   branches/release/boost/integer/ (props changed)
   branches/release/boost/interprocess/ (props changed)
   branches/release/boost/intrusive/ (props changed)
   branches/release/boost/numeric/ublas/ (props changed)
   branches/release/boost/program_options/ (props changed)
   branches/release/boost/property_tree/ (props changed)
   branches/release/boost/python/ (props changed)
   branches/release/boost/regex/ (props changed)
   branches/release/boost/signals/ (props changed)
   branches/release/boost/signals2/ (props changed)
   branches/release/boost/spirit/ (props changed)
   branches/release/boost/spirit/home/ (props changed)
   branches/release/boost/spirit/home/karma/ (props changed)
   branches/release/boost/spirit/home/support/attributes.hpp (props changed)
   branches/release/boost/statechart/ (props changed)
   branches/release/boost/system/ (props changed)
   branches/release/boost/thread/ (props changed)
   branches/release/boost/thread.hpp (props changed)
   branches/release/boost/tr1/ (props changed)
   branches/release/boost/type_traits/ (props changed)
   branches/release/boost/utility/ (props changed)
   branches/release/boost/utility/value_init.hpp (props changed)
   branches/release/boost/uuid/ (props changed)
   branches/release/boost/variant/ (props changed)
   branches/release/boost/version.hpp (props changed)
   branches/release/boost/wave/ (props changed)
   branches/release/bootstrap.bat (props changed)
   branches/release/bootstrap.sh (props changed)
   branches/release/doc/ (props changed)
   branches/release/index.htm (props changed)
   branches/release/index.html (props changed)
   branches/release/libs/ (props changed)
   branches/release/libs/array/doc/array.xml (props changed)
   branches/release/libs/bimap/ (props changed)
   branches/release/libs/filesystem/ (props changed)
   branches/release/libs/functional/hash/ (props changed)
   branches/release/libs/fusion/ (props changed)
   branches/release/libs/graph_parallel/ (props changed)
   branches/release/libs/integer/ (props changed)
   branches/release/libs/interprocess/ (props changed)
   branches/release/libs/intrusive/ (props changed)
   branches/release/libs/libraries.htm (props changed)
   branches/release/libs/maintainers.txt (props changed)
   branches/release/libs/mpl/doc/refmanual/broken-compiler-workarounds.html (props changed)
   branches/release/libs/mpl/doc/refmanual/categorized-index-concepts.html (props changed)
   branches/release/libs/mpl/doc/refmanual/cfg-no-preprocessed-headers.html (props changed)
   branches/release/libs/mpl/doc/refmanual/composition-and-argument-binding.html (props changed)
   branches/release/libs/mpl/doc/refmanual/data-types-concepts.html (props changed)
   branches/release/libs/mpl/doc/refmanual/data-types-miscellaneous.html (props changed)
   branches/release/libs/mpl/doc/refmanual/extensible-associative-sequence.html (props changed)
   branches/release/libs/mpl/doc/refmanual/inserter-class.html (props changed)
   branches/release/libs/mpl/doc/refmanual/tag-dispatched-metafunction.html (props changed)
   branches/release/libs/mpl/doc/refmanual/trivial-metafunctions-summary.html (props changed)
   branches/release/libs/mpl/doc/src/refmanual/Iterators-Iterator.rst (props changed)
   branches/release/libs/numeric/ublas/ (props changed)
   branches/release/libs/numeric/ublas/doc/ (props changed)
   branches/release/libs/program_options/ (props changed)
   branches/release/libs/property_tree/ (props changed)
   branches/release/libs/python/ (props changed)
   branches/release/libs/regex/ (props changed)
   branches/release/libs/regex/doc/ (props changed)
   branches/release/libs/signals/ (props changed)
   branches/release/libs/signals2/ (props changed)
   branches/release/libs/spirit/ (props changed)
   branches/release/libs/spirit/classic/example/ (props changed)
   branches/release/libs/spirit/doc/ (props changed)
   branches/release/libs/spirit/example/ (props changed)
   branches/release/libs/spirit/phoenix/ (props changed)
   branches/release/libs/spirit/test/ (props changed)
   branches/release/libs/spirit/test/qi/optional.cpp (props changed)
   branches/release/libs/statechart/ (props changed)
   branches/release/libs/static_assert/ (props changed)
   branches/release/libs/system/ (props changed)
   branches/release/libs/thread/ (props changed)
   branches/release/libs/thread/doc/ (props changed)
   branches/release/libs/timer/ (props changed)
   branches/release/libs/tr1/ (props changed)
   branches/release/libs/type_traits/ (props changed)
   branches/release/libs/utility/ (props changed)
   branches/release/libs/utility/swap.html (props changed)
   branches/release/libs/utility/value_init.htm (props changed)
   branches/release/libs/utility/value_init_test.cpp (props changed)
   branches/release/libs/uuid/ (props changed)
   branches/release/libs/wave/ (props changed)
   branches/release/more/ (props changed)
   branches/release/people/ (props changed)
   branches/release/rst.css (props changed)
   branches/release/status/ (props changed)
   branches/release/status/Jamfile.v2 (props changed)
   branches/release/tools/ (props changed)
   branches/release/tools/bcp/ (props changed)
   branches/release/tools/boostbook/ (props changed)
   branches/release/tools/build/v2/ (props changed)
   branches/release/tools/inspect/ (props changed)
   branches/release/tools/regression/ (props changed)
   branches/release/tools/release/ (props changed)
   branches/release/tools/wave/ (props changed)
   branches/release/wiki/ (props changed)
Text files modified:
   branches/release/boost/asio/buffers_iterator.hpp | 138 +++
   branches/release/boost/asio/datagram_socket_service.hpp | 29
   branches/release/boost/asio/deadline_timer_service.hpp | 36
   branches/release/boost/asio/detail/consuming_buffers.hpp | 54 +
   branches/release/boost/asio/detail/deadline_timer_service.hpp | 63
   branches/release/boost/asio/detail/dev_poll_reactor.hpp | 408 ++-------
   branches/release/boost/asio/detail/dev_poll_reactor_fwd.hpp | 1
   branches/release/boost/asio/detail/epoll_reactor.hpp | 749 ++++++-----------
   branches/release/boost/asio/detail/epoll_reactor_fwd.hpp | 1
   branches/release/boost/asio/detail/hash_map.hpp | 93 +
   branches/release/boost/asio/detail/kqueue_reactor.hpp | 476 ++--------
   branches/release/boost/asio/detail/kqueue_reactor_fwd.hpp | 1
   branches/release/boost/asio/detail/null_event.hpp | 6
   branches/release/boost/asio/detail/posix_event.hpp | 10
   branches/release/boost/asio/detail/posix_mutex.hpp | 22
   branches/release/boost/asio/detail/reactive_descriptor_service.hpp | 486 ++++------
   branches/release/boost/asio/detail/reactive_serial_port_service.hpp | 25
   branches/release/boost/asio/detail/reactive_socket_service.hpp | 1160 ++++++++++++--------------
   branches/release/boost/asio/detail/reactor_op_queue.hpp | 383 +-------
   branches/release/boost/asio/detail/resolver_service.hpp | 241 +++-
   branches/release/boost/asio/detail/select_reactor.hpp | 455 +++-------
   branches/release/boost/asio/detail/service_registry.hpp | 175 ++-
   branches/release/boost/asio/detail/strand_service.hpp | 445 +++-------
   branches/release/boost/asio/detail/task_io_service.hpp | 293 +++---
   branches/release/boost/asio/detail/timer_queue.hpp | 338 ++-----
   branches/release/boost/asio/detail/timer_queue_base.hpp | 32
   branches/release/boost/asio/detail/win_event.hpp | 9
   branches/release/boost/asio/detail/win_iocp_handle_service.hpp | 427 +++------
   branches/release/boost/asio/detail/win_iocp_io_service.hpp | 545 +++++-------
   branches/release/boost/asio/detail/win_iocp_overlapped_ptr.hpp | 124 +-
   branches/release/boost/asio/detail/win_iocp_serial_port_service.hpp | 10
   branches/release/boost/asio/detail/win_iocp_socket_service.hpp | 1699 +++++++++++++++------------------------
   branches/release/boost/asio/detail/win_mutex.hpp | 42
   branches/release/boost/asio/impl/io_service.ipp | 12
   branches/release/boost/asio/impl/read.ipp | 202 ++-
   branches/release/boost/asio/impl/read_at.ipp | 8
   branches/release/boost/asio/impl/write.ipp | 180 +++
   branches/release/boost/asio/impl/write_at.ipp | 8
   branches/release/boost/asio/io_service.hpp | 31
   branches/release/boost/asio/ip/basic_resolver_iterator.hpp | 76 +
   branches/release/boost/asio/posix/stream_descriptor_service.hpp | 35
   branches/release/boost/asio/raw_socket_service.hpp | 29
   branches/release/boost/asio/serial_port_service.hpp | 19
   branches/release/boost/asio/socket_acceptor_service.hpp | 29
   branches/release/boost/asio/ssl/detail/openssl_operation.hpp | 3
   branches/release/boost/asio/ssl/detail/openssl_stream_service.hpp | 59 +
   branches/release/boost/asio/stream_socket_service.hpp | 29
   branches/release/boost/asio/windows/random_access_handle_service.hpp | 7
   branches/release/boost/asio/windows/stream_handle_service.hpp | 7
   49 files changed, 3946 insertions(+), 5764 deletions(-)

Modified: branches/release/boost/asio/buffers_iterator.hpp
==============================================================================
--- branches/release/boost/asio/buffers_iterator.hpp (original)
+++ branches/release/boost/asio/buffers_iterator.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -22,7 +22,7 @@
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
-#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/add_const.hpp>
 #include <boost/asio/detail/pop_options.hpp>
@@ -76,11 +76,10 @@
 /// A random access iterator over the bytes in a buffer sequence.
 template <typename BufferSequence, typename ByteType = char>
 class buffers_iterator
- : public boost::iterator_facade<
- buffers_iterator<BufferSequence, ByteType>,
- typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::byte_type,
- boost::random_access_traversal_tag>
+ : public boost::iterator<
+ std::random_access_iterator_tag,
+ typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::byte_type>
 {
 private:
   typedef typename detail::buffers_iterator_types<
@@ -139,9 +138,132 @@
     return new_iter;
   }
 
-private:
- friend class boost::iterator_core_access;
+ /// Dereference an iterator.
+ byte_type& operator*() const
+ {
+ return dereference();
+ }
+
+ /// Dereference an iterator.
+ byte_type* operator->() const
+ {
+ return &dereference();
+ }
+
+ /// Access an individual element.
+ byte_type& operator[](std::ptrdiff_t difference) const
+ {
+ buffers_iterator tmp(*this);
+ tmp.advance(difference);
+ return *tmp;
+ }
+
+ /// Increment operator (prefix).
+ buffers_iterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ /// Increment operator (postfix).
+ buffers_iterator operator++(int)
+ {
+ buffers_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ /// Decrement operator (prefix).
+ buffers_iterator& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ /// Decrement operator (postfix).
+ buffers_iterator operator--(int)
+ {
+ buffers_iterator tmp(*this);
+ --*this;
+ return tmp;
+ }
+
+ /// Addition operator.
+ buffers_iterator& operator+=(std::ptrdiff_t difference)
+ {
+ advance(difference);
+ return *this;
+ }
+
+ /// Subtraction operator.
+ buffers_iterator& operator-=(std::ptrdiff_t difference)
+ {
+ advance(-difference);
+ return *this;
+ }
 
+ /// Addition operator.
+ friend buffers_iterator operator+(const buffers_iterator& iter,
+ std::ptrdiff_t difference)
+ {
+ buffers_iterator tmp(iter);
+ tmp.advance(difference);
+ return tmp;
+ }
+
+ /// Subtraction operator.
+ friend buffers_iterator operator-(const buffers_iterator& iter,
+ std::ptrdiff_t difference)
+ {
+ buffers_iterator tmp(iter);
+ tmp.advance(-difference);
+ return tmp;
+ }
+
+ /// Subtraction operator.
+ friend std::ptrdiff_t operator-(const buffers_iterator& a,
+ const buffers_iterator& b)
+ {
+ return b.distance_to(a);
+ }
+
+ /// Test two iterators for equality.
+ friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return a.equal(b);
+ }
+
+ /// Test two iterators for inequality.
+ friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return !a.equal(b);
+ }
+
+ /// Compare two iterators.
+ friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return a.distance_to(b) > 0;
+ }
+
+ /// Compare two iterators.
+ friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return !(b < a);
+ }
+
+ /// Compare two iterators.
+ friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return b < a;
+ }
+
+ /// Compare two iterators.
+ friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
+ {
+ return !(a < b);
+ }
+
+private:
   // Dereference the iterator.
   byte_type& dereference() const
   {

Modified: branches/release/boost/asio/datagram_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/datagram_socket_service.hpp (original)
+++ branches/release/boost/asio/datagram_socket_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -28,17 +28,7 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 # include <boost/asio/detail/win_iocp_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
 #else
-# include <boost/asio/detail/select_reactor.hpp>
 # include <boost/asio/detail/reactive_socket_service.hpp>
 #endif
 
@@ -70,18 +60,8 @@
   // The type of the platform-specific implementation.
 #if defined(BOOST_ASIO_HAS_IOCP)
   typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_socket_service<
- Protocol, detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::dev_poll_reactor<false> > service_impl_type;
 #else
- typedef detail::reactive_socket_service<
- Protocol, detail::select_reactor<false> > service_impl_type;
+ typedef detail::reactive_socket_service<Protocol> service_impl_type;
 #endif
 
 public:
@@ -103,13 +83,14 @@
   explicit datagram_socket_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         datagram_socket_service<Protocol> >(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new datagram socket implementation.
@@ -324,8 +305,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Modified: branches/release/boost/asio/deadline_timer_service.hpp
==============================================================================
--- branches/release/boost/asio/deadline_timer_service.hpp (original)
+++ branches/release/boost/asio/deadline_timer_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -27,18 +27,6 @@
 #include <boost/asio/detail/deadline_timer_service.hpp>
 #include <boost/asio/detail/service_base.hpp>
 
-#if defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/win_iocp_io_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-#else
-# include <boost/asio/detail/select_reactor.hpp>
-#endif
-
 namespace boost {
 namespace asio {
 
@@ -70,22 +58,7 @@
 
 private:
   // The type of the platform-specific implementation.
-#if defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::deadline_timer_service<
- traits_type, detail::win_iocp_io_service> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::deadline_timer_service<
- traits_type, detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::deadline_timer_service<
- traits_type, detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::deadline_timer_service<
- traits_type, detail::dev_poll_reactor<false> > service_impl_type;
-#else
- typedef detail::deadline_timer_service<
- traits_type, detail::select_reactor<false> > service_impl_type;
-#endif
+ typedef detail::deadline_timer_service<traits_type> service_impl_type;
 
 public:
   /// The implementation type of the deadline timer.
@@ -99,13 +72,14 @@
   explicit deadline_timer_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         deadline_timer_service<TimeType, TimeTraits> >(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new timer implementation.
@@ -166,8 +140,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Deleted: branches/release/boost/asio/detail/const_buffers_iterator.hpp
==============================================================================
--- branches/release/boost/asio/detail/const_buffers_iterator.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
+++ (empty file)
@@ -1,153 +0,0 @@
-//
-// const_buffers_iterator.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_CONST_BUFFERS_ITERATOR_HPP
-#define BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_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/push_options.hpp>
-#include <cstddef>
-#include <boost/config.hpp>
-#include <boost/iterator/iterator_facade.hpp>
-#include <boost/asio/detail/pop_options.hpp>
-
-#include <boost/asio/buffer.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-// A proxy iterator for a sub-range in a list of buffers.
-template <typename ConstBufferSequence>
-class const_buffers_iterator
- : public boost::iterator_facade<const_buffers_iterator<ConstBufferSequence>,
- const char, boost::bidirectional_traversal_tag>
-{
-public:
- // Default constructor creates an iterator in an undefined state.
- const_buffers_iterator()
- {
- }
-
- // Create an iterator for the specified position.
- const_buffers_iterator(const ConstBufferSequence& buffers,
- std::size_t position)
- : begin_(buffers.begin()),
- current_(buffers.begin()),
- end_(buffers.end()),
- position_(0)
- {
- while (current_ != end_)
- {
- current_buffer_ = *current_;
- std::size_t buffer_size = boost::asio::buffer_size(current_buffer_);
- if (position - position_ < buffer_size)
- {
- current_buffer_position_ = position - position_;
- position_ = position;
- return;
- }
- position_ += buffer_size;
- ++current_;
- }
- current_buffer_ = boost::asio::const_buffer();
- current_buffer_position_ = 0;
- }
-
- std::size_t position() const
- {
- return position_;
- }
-
-private:
- friend class boost::iterator_core_access;
-
- void increment()
- {
- if (current_ == end_)
- return;
-
- ++position_;
-
- ++current_buffer_position_;
- if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
- return;
-
- ++current_;
- current_buffer_position_ = 0;
- while (current_ != end_)
- {
- current_buffer_ = *current_;
- if (boost::asio::buffer_size(current_buffer_) > 0)
- return;
- ++current_;
- }
- }
-
- void decrement()
- {
- if (position_ == 0)
- return;
-
- --position_;
-
- if (current_buffer_position_ != 0)
- {
- --current_buffer_position_;
- return;
- }
-
- typename ConstBufferSequence::const_iterator iter = current_;
- while (iter != begin_)
- {
- --iter;
- boost::asio::const_buffer buffer = *iter;
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
- if (buffer_size > 0)
- {
- current_ = iter;
- current_buffer_ = buffer;
- current_buffer_position_ = buffer_size - 1;
- return;
- }
- }
- }
-
- bool equal(const const_buffers_iterator& other) const
- {
- return position_ == other.position_;
- }
-
- const char& dereference() const
- {
- return boost::asio::buffer_cast<const char*>(
- current_buffer_)[current_buffer_position_];
- }
-
- boost::asio::const_buffer current_buffer_;
- std::size_t current_buffer_position_;
- typename ConstBufferSequence::const_iterator begin_;
- typename ConstBufferSequence::const_iterator current_;
- typename ConstBufferSequence::const_iterator end_;
- std::size_t position_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP

Modified: branches/release/boost/asio/detail/consuming_buffers.hpp
==============================================================================
--- branches/release/boost/asio/detail/consuming_buffers.hpp (original)
+++ branches/release/boost/asio/detail/consuming_buffers.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -21,12 +21,11 @@
 #include <algorithm>
 #include <cstddef>
 #include <boost/config.hpp>
-#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator.hpp>
 #include <boost/limits.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/buffer.hpp>
-#include <boost/asio/completion_condition.hpp>
 
 namespace boost {
 namespace asio {
@@ -35,9 +34,7 @@
 // A proxy iterator for a sub-range in a list of buffers.
 template <typename Buffer, typename Buffer_Iterator>
 class consuming_buffers_iterator
- : public boost::iterator_facade<
- consuming_buffers_iterator<Buffer, Buffer_Iterator>,
- const Buffer, boost::forward_traversal_tag>
+ : public boost::iterator<std::forward_iterator_tag, const Buffer>
 {
 public:
   // Default constructor creates an end iterator.
@@ -60,9 +57,48 @@
   {
   }
 
-private:
- friend class boost::iterator_core_access;
+ // Dereference an iterator.
+ const Buffer& operator*() const
+ {
+ return dereference();
+ }
+
+ // Dereference an iterator.
+ const Buffer* operator->() const
+ {
+ return &dereference();
+ }
+
+ // Increment operator (prefix).
+ consuming_buffers_iterator& operator++()
+ {
+ increment();
+ return *this;
+ }
 
+ // Increment operator (postfix).
+ consuming_buffers_iterator operator++(int)
+ {
+ consuming_buffers_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ // Test two iterators for equality.
+ friend bool operator==(const consuming_buffers_iterator& a,
+ const consuming_buffers_iterator& b)
+ {
+ return a.equal(b);
+ }
+
+ // Test two iterators for inequality.
+ friend bool operator!=(const consuming_buffers_iterator& a,
+ const consuming_buffers_iterator& b)
+ {
+ return !a.equal(b);
+ }
+
+private:
   void increment()
   {
     if (!at_end_)
@@ -170,7 +206,7 @@
   }
 
   // Set the maximum size for a single transfer.
- void set_max_size(std::size_t max_size)
+ void prepare(std::size_t max_size)
   {
     max_size_ = max_size;
   }
@@ -226,7 +262,7 @@
     // No-op.
   }
 
- void set_max_size(std::size_t)
+ void prepare(std::size_t)
   {
     // No-op.
   }

Modified: branches/release/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/deadline_timer_service.hpp (original)
+++ branches/release/boost/asio/detail/deadline_timer_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -26,21 +26,20 @@
 #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/fenced_block.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_scheduler.hpp>
 
 namespace boost {
 namespace asio {
 namespace detail {
 
-template <typename Time_Traits, typename Timer_Scheduler>
+template <typename Time_Traits>
 class deadline_timer_service
- : public boost::asio::detail::service_base<
- deadline_timer_service<Time_Traits, Timer_Scheduler> >
 {
 public:
   // The time type.
@@ -60,9 +59,7 @@
 
   // Constructor.
   deadline_timer_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
- scheduler_(boost::asio::use_service<Timer_Scheduler>(io_service))
+ : scheduler_(boost::asio::use_service<timer_scheduler>(io_service))
   {
     scheduler_.init_task();
     scheduler_.add_timer_queue(timer_queue_);
@@ -156,34 +153,58 @@
   }
 
   template <typename Handler>
- class wait_handler :
- public handler_base_from_member<Handler>
+ class wait_handler : public timer_op
   {
   public:
- wait_handler(boost::asio::io_service& io_service, Handler handler)
- : handler_base_from_member<Handler>(handler),
- io_service_(io_service),
- work_(io_service)
+ wait_handler(Handler handler)
+ : timer_op(&wait_handler::do_complete),
+ handler_(handler)
     {
     }
 
- void operator()(const boost::system::error_code& result)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
     {
- io_service_.post(detail::bind_handler(this->handler_, result));
+ // Take ownership of the handler object.
+ wait_handler* h(static_cast<wait_handler*>(base));
+ typedef handler_alloc_traits<Handler, wait_handler> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder1<Handler, boost::system::error_code>
+ handler(h->handler_, h->ec_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   private:
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
+ Handler handler_;
   };
 
   // Start an asynchronous wait on the timer.
   template <typename Handler>
   void async_wait(implementation_type& impl, Handler handler)
   {
+ // Allocate and construct an operation to wrap the handler.
+ typedef wait_handler<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
     impl.might_have_pending_waits = true;
- scheduler_.schedule_timer(timer_queue_, impl.expiry,
- wait_handler<Handler>(this->get_io_service(), handler), &impl);
+
+ scheduler_.schedule_timer(timer_queue_, impl.expiry, ptr.get(), &impl);
+ ptr.release();
   }
 
 private:
@@ -191,7 +212,7 @@
   timer_queue<Time_Traits> timer_queue_;
 
   // The object that schedules and executes timers. Usually a reactor.
- Timer_Scheduler& scheduler_;
+ timer_scheduler& scheduler_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ branches/release/boost/asio/detail/dev_poll_reactor.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -33,27 +33,30 @@
 
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/hash_map.hpp>
 #include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/task_io_service.hpp>
-#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/service_base.hpp>
-#include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/timer_queue_fwd.hpp>
+#include <boost/asio/detail/timer_queue_set.hpp>
 
 namespace boost {
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class dev_poll_reactor
- : public boost::asio::detail::service_base<dev_poll_reactor<Own_Thread> >
+ : public boost::asio::detail::service_base<dev_poll_reactor>
 {
 public:
+ enum { read_op = 0, write_op = 1,
+ connect_op = 1, except_op = 2, max_ops = 3 };
+
   // Per-descriptor data.
   struct per_descriptor_data
   {
@@ -61,28 +64,13 @@
 
   // Constructor.
   dev_poll_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- dev_poll_reactor<Own_Thread> >(io_service),
+ : boost::asio::detail::service_base<dev_poll_reactor>(io_service),
+ io_service_(use_service<io_service_impl>(io_service)),
       mutex_(),
       dev_poll_fd_(do_dev_poll_create()),
- wait_in_progress_(false),
       interrupter_(),
- read_op_queue_(),
- write_op_queue_(),
- except_op_queue_(),
- pending_cancellations_(),
- stop_thread_(false),
- thread_(0),
       shutdown_(false)
   {
- // Start the reactor's internal thread only if needed.
- if (Own_Thread)
- {
- boost::asio::detail::signal_blocker sb;
- thread_ = new boost::asio::detail::thread(
- bind_handler(&dev_poll_reactor::call_run_thread, this));
- }
-
     // Add the interrupter's descriptor to /dev/poll.
     ::pollfd ev = { 0 };
     ev.fd = interrupter_.read_descriptor();
@@ -103,35 +91,20 @@
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     shutdown_ = true;
- stop_thread_ = true;
     lock.unlock();
 
- if (thread_)
- {
- interrupter_.interrupt();
- thread_->join();
- delete thread_;
- thread_ = 0;
- }
+ op_queue<operation> ops;
+
+ for (int i = 0; i < max_ops; ++i)
+ op_queue_[i].get_all_operations(ops);
 
- read_op_queue_.destroy_operations();
- write_op_queue_.destroy_operations();
- except_op_queue_.destroy_operations();
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- timer_queues_[i]->destroy_timers();
- timer_queues_.clear();
+ timer_queues_.get_all_timers(ops);
   }
 
- // Initialise the task, but only if the reactor is not in its own thread.
+ // Initialise the task.
   void init_task()
   {
- if (!Own_Thread)
- {
- typedef task_io_service<dev_poll_reactor<Own_Thread> >
- task_io_service_type;
- use_service<task_io_service_type>(this->get_io_service()).init_task();
- }
+ io_service_.init_task();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -141,121 +114,44 @@
     return 0;
   }
 
- // Start a new read operation. The handler object will be invoked when the
- // given descriptor is ready to be read, or an error has occurred.
- template <typename Handler>
- void start_read_op(socket_type descriptor, per_descriptor_data&,
- Handler handler, bool allow_speculative_read = true)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (allow_speculative_read)
- {
- if (!read_op_queue_.has_operation(descriptor))
- {
- 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))
- {
- ::pollfd& ev = add_pending_event_change(descriptor);
- ev.events = POLLIN | POLLERR | POLLHUP;
- if (write_op_queue_.has_operation(descriptor))
- ev.events |= POLLOUT;
- if (except_op_queue_.has_operation(descriptor))
- ev.events |= POLLPRI;
- interrupter_.interrupt();
- }
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready to be written, or an error has occurred.
- template <typename Handler>
- void start_write_op(socket_type descriptor, per_descriptor_data&,
- Handler handler, bool allow_speculative_write = true)
+ // Start a new operation. The reactor operation will be performed when the
+ // given descriptor is flagged as ready, or an error has occurred.
+ void start_op(int op_type, socket_type descriptor,
+ per_descriptor_data&, reactor_op* op, bool allow_speculative)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
     if (shutdown_)
       return;
 
- if (allow_speculative_write)
+ if (allow_speculative)
     {
- if (!write_op_queue_.has_operation(descriptor))
+ if (!op_queue_[op_type].has_operation(descriptor))
       {
- boost::system::error_code ec;
- std::size_t bytes_transferred = 0;
- if (handler.perform(ec, bytes_transferred))
+ if (op->perform())
         {
- handler.complete(ec, bytes_transferred);
+ lock.unlock();
+ io_service_.post_immediate_completion(op);
           return;
         }
       }
     }
 
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- ::pollfd& ev = add_pending_event_change(descriptor);
- ev.events = POLLOUT | POLLERR | POLLHUP;
- if (read_op_queue_.has_operation(descriptor))
- ev.events |= POLLIN;
- if (except_op_queue_.has_operation(descriptor))
- ev.events |= POLLPRI;
- interrupter_.interrupt();
- }
- }
 
- // Start a new exception operation. The handler object will be invoked when
- // the given descriptor has exception information, or an error has occurred.
- template <typename Handler>
- void start_except_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (except_op_queue_.enqueue_operation(descriptor, handler))
+ bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+ io_service_.work_started();
+ if (first)
     {
       ::pollfd& ev = add_pending_event_change(descriptor);
- ev.events = POLLPRI | POLLERR | POLLHUP;
- if (read_op_queue_.has_operation(descriptor))
+ ev.events = POLLERR | POLLHUP;
+ if (op_type == read_op
+ || op_queue_[read_op].has_operation(descriptor))
         ev.events |= POLLIN;
- if (write_op_queue_.has_operation(descriptor))
+ if (op_type == write_op
+ || op_queue_[write_op].has_operation(descriptor))
         ev.events |= POLLOUT;
- interrupter_.interrupt();
- }
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // information available, or an error has occurred.
- template <typename Handler>
- void start_connect_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- ::pollfd& ev = add_pending_event_change(descriptor);
- ev.events = POLLOUT | POLLERR | POLLHUP;
- if (read_op_queue_.has_operation(descriptor))
- ev.events |= POLLIN;
- if (except_op_queue_.has_operation(descriptor))
+ if (op_type == except_op
+ || op_queue_[except_op].has_operation(descriptor))
         ev.events |= POLLPRI;
       interrupter_.interrupt();
     }
@@ -267,7 +163,7 @@
   void cancel_ops(socket_type descriptor, per_descriptor_data&)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- cancel_ops_unlocked(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Cancel any operations that are running against the descriptor and remove
@@ -282,7 +178,7 @@
     interrupter_.interrupt();
 
     // Cancel any outstanding operations associated with the descriptor.
- cancel_ops_unlocked(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Add a new timer queue to the reactor.
@@ -290,7 +186,7 @@
   void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- timer_queues_.push_back(&timer_queue);
+ timer_queues_.insert(&timer_queue);
   }
 
   // Remove a timer queue from the reactor.
@@ -298,71 +194,48 @@
   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- if (timer_queues_[i] == &timer_queue)
- {
- timer_queues_.erase(timer_queues_.begin() + i);
- return;
- }
- }
+ timer_queues_.erase(&timer_queue);
   }
 
- // Schedule a timer in the given timer queue to expire at the specified
- // absolute time. The handler object will be invoked when the timer expires.
- template <typename Time_Traits, typename Handler>
+ // 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, Handler handler, void* token)
+ const typename Time_Traits::time_type& time, timer_op* op, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
- if (timer_queue.enqueue_timer(time, handler, token))
+ {
+ bool earliest = timer_queue.enqueue_timer(time, op, token);
+ io_service_.work_started();
+ if (earliest)
         interrupter_.interrupt();
+ }
   }
 
- // Cancel the timer associated with the given token. Returns the number of
- // handlers that have been posted or dispatched.
+ // 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)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- std::size_t n = timer_queue.cancel_timer(token);
- if (n > 0)
- interrupter_.interrupt();
+ op_queue<operation> ops;
+ std::size_t n = timer_queue.cancel_timer(token, ops);
+ lock.unlock();
+ io_service_.post_deferred_completions(ops);
     return n;
   }
 
-private:
- friend class task_io_service<dev_poll_reactor<Own_Thread> >;
-
   // Run /dev/poll once until interrupted or events are ready to be dispatched.
- void run(bool block)
+ void run(bool block, op_queue<operation>& ops)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- // Dispatch any operation cancellations that were made while the select
- // loop was not running.
- 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_)
- {
- complete_operations_and_timers(lock);
- return;
- }
-
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
- if (!block && read_op_queue_.empty() && write_op_queue_.empty()
- && except_op_queue_.empty() && all_timer_queues_are_empty())
- {
- complete_operations_and_timers(lock);
+ if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+ && op_queue_[except_op].empty() && timer_queues_.all_empty())
       return;
- }
 
     // Write the pending event registration changes to the /dev/poll descriptor.
     std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
@@ -373,14 +246,13 @@
           &pending_event_changes_[0], events_size);
       if (result != static_cast<int>(events_size))
       {
+ boost::system::error_code ec = boost::system::error_code(
+ errno, boost::asio::error::get_system_category());
         for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
         {
           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_.perform_all_operations(descriptor, ec);
- write_op_queue_.perform_all_operations(descriptor, ec);
- except_op_queue_.perform_all_operations(descriptor, ec);
+ for (int j = 0; j < max_ops; ++j)
+ op_queue_[j].cancel_operations(descriptor, ops, ec);
         }
       }
       pending_event_changes_.clear();
@@ -388,7 +260,6 @@
     }
 
     int timeout = block ? get_timeout() : 0;
- wait_in_progress_ = true;
     lock.unlock();
 
     // Block on the /dev/poll descriptor.
@@ -400,7 +271,6 @@
     int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
 
     lock.lock();
- wait_in_progress_ = false;
 
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
@@ -415,24 +285,24 @@
         bool more_reads = false;
         bool more_writes = false;
         bool more_except = false;
- boost::system::error_code ec;
 
         // 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_.perform_operation(descriptor, ec);
+ more_except =
+ op_queue_[except_op].perform_operations(descriptor, ops);
         else
- more_except = except_op_queue_.has_operation(descriptor);
+ more_except = op_queue_[except_op].has_operation(descriptor);
 
         if (events[i].events & (POLLIN | POLLERR | POLLHUP))
- more_reads = read_op_queue_.perform_operation(descriptor, ec);
+ more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
         else
- more_reads = read_op_queue_.has_operation(descriptor);
+ more_reads = op_queue_[read_op].has_operation(descriptor);
 
         if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
- more_writes = write_op_queue_.perform_operation(descriptor, ec);
+ more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
         else
- more_writes = write_op_queue_.has_operation(descriptor);
+ more_writes = op_queue_[write_op].has_operation(descriptor);
 
         if ((events[i].events & (POLLERR | POLLHUP)) != 0
               && !more_except && !more_reads && !more_writes)
@@ -463,48 +333,15 @@
           int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
           if (result != sizeof(ev))
           {
- ec = boost::system::error_code(errno,
+ boost::system::error_code ec(errno,
                 boost::asio::error::get_system_category());
- read_op_queue_.perform_all_operations(descriptor, ec);
- write_op_queue_.perform_all_operations(descriptor, ec);
- except_op_queue_.perform_all_operations(descriptor, ec);
+ for (int j = 0; j < max_ops; ++j)
+ op_queue_[j].cancel_operations(descriptor, ops, ec);
           }
         }
       }
     }
- 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();
- timer_queues_[i]->dispatch_cancellations();
- }
-
- // Issue any pending cancellations.
- for (size_t i = 0; i < pending_cancellations_.size(); ++i)
- cancel_ops_unlocked(pending_cancellations_[i]);
- pending_cancellations_.clear();
-
- complete_operations_and_timers(lock);
- }
-
- // Run the select loop in the thread.
- void run_thread()
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- while (!stop_thread_)
- {
- lock.unlock();
- run(true);
- lock.lock();
- }
- }
-
- // Entry point for the select loop thread.
- static void call_run_thread(dev_poll_reactor* reactor)
- {
- reactor->run_thread();
+ timer_queues_.get_ready_timers(ops);
   }
 
   // Interrupt the select loop.
@@ -513,6 +350,7 @@
     interrupter_.interrupt();
   }
 
+private:
   // Create the /dev/poll file descriptor. Throws an exception if the descriptor
   // cannot be created.
   static int do_dev_poll_create()
@@ -529,75 +367,32 @@
     return fd;
   }
 
- // Check if all timer queues are empty.
- bool all_timer_queues_are_empty() const
- {
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- if (!timer_queues_[i]->empty())
- return false;
- return true;
- }
-
   // Get the timeout value for the /dev/poll DP_POLL operation. The timeout
   // value is returned as a number of milliseconds. A return value of -1
   // indicates that the poll should block indefinitely.
   int get_timeout()
   {
- if (all_timer_queues_are_empty())
- return -1;
-
     // By default we will wait no longer than 5 minutes. This will ensure that
     // any changes to the system clock are detected after no longer than this.
- boost::posix_time::time_duration minimum_wait_duration
- = boost::posix_time::minutes(5);
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- boost::posix_time::time_duration wait_duration
- = timer_queues_[i]->wait_duration();
- if (wait_duration < minimum_wait_duration)
- minimum_wait_duration = wait_duration;
- }
-
- if (minimum_wait_duration > boost::posix_time::time_duration())
- {
- int milliseconds = minimum_wait_duration.total_milliseconds();
- return milliseconds > 0 ? milliseconds : 1;
- }
- else
- {
- return 0;
- }
+ return timer_queues_.wait_duration_msec(5 * 60 * 1000);
   }
 
   // Cancel all operations associated with the given descriptor. The do_cancel
   // function of the handler objects will be invoked. This function does not
   // acquire the dev_poll_reactor's mutex.
- void cancel_ops_unlocked(socket_type descriptor)
+ void cancel_ops_unlocked(socket_type descriptor,
+ const boost::system::error_code& ec)
   {
- bool interrupt = read_op_queue_.cancel_operations(descriptor);
- interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
- interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
- if (interrupt)
+ bool need_interrupt = false;
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
+ need_interrupt = op_queue_[i].cancel_operations(
+ descriptor, ops, ec) || need_interrupt;
+ io_service_.post_deferred_completions(ops);
+ if (need_interrupt)
       interrupter_.interrupt();
   }
 
- // Clean up operations and timers. We must not hold the lock since the
- // 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 complete_operations_and_timers(
- boost::asio::detail::mutex::scoped_lock& lock)
- {
- timer_queues_for_cleanup_ = timer_queues_;
- lock.unlock();
- 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]->complete_timers();
- }
-
   // Add a pending event entry for the given descriptor.
   ::pollfd& add_pending_event_change(int descriptor)
   {
@@ -619,6 +414,9 @@
     }
   }
 
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_;
+
   // Mutex to protect access to internal data.
   boost::asio::detail::mutex mutex_;
 
@@ -631,36 +429,14 @@
   // Hash map to associate a descriptor with a pending event change index.
   hash_map<int, std::size_t> pending_event_change_index_;
 
- // Whether the DP_POLL operation is currently in progress
- bool wait_in_progress_;
-
   // The interrupter is used to break a blocking DP_POLL operation.
   select_interrupter interrupter_;
 
- // The queue of read operations.
- reactor_op_queue<socket_type> read_op_queue_;
-
- // The queue of write operations.
- reactor_op_queue<socket_type> write_op_queue_;
-
- // The queue of except operations.
- reactor_op_queue<socket_type> except_op_queue_;
+ // The queues of read, write and except operations.
+ reactor_op_queue<socket_type> op_queue_[max_ops];
 
   // The timer queues.
- std::vector<timer_queue_base*> timer_queues_;
-
- // A copy of the timer queues, used when cleaning up timers. The copy is
- // stored as a class data member to avoid unnecessary memory allocation.
- std::vector<timer_queue_base*> timer_queues_for_cleanup_;
-
- // The descriptors that are pending cancellation.
- std::vector<socket_type> pending_cancellations_;
-
- // Does the reactor loop thread need to stop.
- bool stop_thread_;
-
- // The thread that is running the reactor loop.
- boost::asio::detail::thread* thread_;
+ timer_queue_set timer_queues_;
 
   // Whether the service has been shut down.
   bool shutdown_;

Modified: branches/release/boost/asio/detail/dev_poll_reactor_fwd.hpp
==============================================================================
--- branches/release/boost/asio/detail/dev_poll_reactor_fwd.hpp (original)
+++ branches/release/boost/asio/detail/dev_poll_reactor_fwd.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -27,7 +27,6 @@
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class dev_poll_reactor;
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/epoll_reactor.hpp (original)
+++ branches/release/boost/asio/detail/epoll_reactor.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -23,115 +23,126 @@
 
 #include <boost/asio/detail/push_options.hpp>
 #include <cstddef>
-#include <vector>
 #include <sys/epoll.h>
 #include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/system/system_error.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/hash_map.hpp>
 #include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/task_io_service.hpp>
-#include <boost/asio/detail/thread.hpp>
-#include <boost/asio/detail/reactor_op_queue.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/service_base.hpp>
-#include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/timer_queue_fwd.hpp>
+#include <boost/asio/detail/timer_queue_set.hpp>
+
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+# define BOOST_ASIO_HAS_TIMERFD 1
+#endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+# include <boost/asio/detail/push_options.hpp>
+# include <sys/timerfd.h>
+# include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
 
 namespace boost {
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class epoll_reactor
- : public boost::asio::detail::service_base<epoll_reactor<Own_Thread> >
+ : public boost::asio::detail::service_base<epoll_reactor>
 {
 public:
- // Per-descriptor data.
- struct per_descriptor_data
+ enum { read_op = 0, write_op = 1,
+ connect_op = 1, except_op = 2, max_ops = 3 };
+
+ // Per-descriptor queues.
+ struct descriptor_state
   {
- bool allow_speculative_read;
- bool allow_speculative_write;
+ descriptor_state() {}
+ descriptor_state(const descriptor_state&) {}
+ void operator=(const descriptor_state&) {}
+
+ mutex mutex_;
+ op_queue<reactor_op> op_queue_[max_ops];
+ bool shutdown_;
   };
 
+ // Per-descriptor data.
+ typedef descriptor_state* per_descriptor_data;
+
   // Constructor.
   epoll_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<epoll_reactor<Own_Thread> >(io_service),
+ : boost::asio::detail::service_base<epoll_reactor>(io_service),
+ io_service_(use_service<io_service_impl>(io_service)),
       mutex_(),
       epoll_fd_(do_epoll_create()),
- wait_in_progress_(false),
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
+#else // defined(BOOST_ASIO_HAS_TIMERFD)
+ timer_fd_(-1),
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
       interrupter_(),
- read_op_queue_(),
- write_op_queue_(),
- except_op_queue_(),
- pending_cancellations_(),
- stop_thread_(false),
- thread_(0),
- shutdown_(false),
- need_epoll_wait_(true)
+ shutdown_(false)
   {
- // Start the reactor's internal thread only if needed.
- if (Own_Thread)
- {
- boost::asio::detail::signal_blocker sb;
- thread_ = new boost::asio::detail::thread(
- bind_handler(&epoll_reactor::call_run_thread, this));
- }
-
     // Add the interrupter's descriptor to epoll.
     epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLIN | EPOLLERR;
- ev.data.fd = interrupter_.read_descriptor();
+ ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+ ev.data.ptr = &interrupter_;
     epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
+ interrupter_.interrupt();
+
+ // Add the timer descriptor to epoll.
+ if (timer_fd_ != -1)
+ {
+ ev.events = EPOLLIN | EPOLLERR;
+ ev.data.ptr = &timer_fd_;
+ epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
+ }
   }
 
   // Destructor.
   ~epoll_reactor()
   {
- shutdown_service();
     close(epoll_fd_);
+ if (timer_fd_ != -1)
+ close(timer_fd_);
   }
 
   // Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ mutex::scoped_lock lock(mutex_);
     shutdown_ = true;
- stop_thread_ = true;
     lock.unlock();
 
- if (thread_)
+ op_queue<operation> ops;
+
+ descriptor_map::iterator iter = registered_descriptors_.begin();
+ descriptor_map::iterator end = registered_descriptors_.end();
+ while (iter != end)
     {
- interrupter_.interrupt();
- thread_->join();
- delete thread_;
- thread_ = 0;
+ for (int i = 0; i < max_ops; ++i)
+ ops.push(iter->second.op_queue_[i]);
+ iter->second.shutdown_ = true;
+ ++iter;
     }
 
- read_op_queue_.destroy_operations();
- write_op_queue_.destroy_operations();
- except_op_queue_.destroy_operations();
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- timer_queues_[i]->destroy_timers();
- timer_queues_.clear();
+ timer_queues_.get_all_timers(ops);
   }
 
- // Initialise the task, but only if the reactor is not in its own thread.
+ // Initialise the task.
   void init_task()
   {
- if (!Own_Thread)
- {
- typedef task_io_service<epoll_reactor<Own_Thread> > task_io_service_type;
- use_service<task_io_service_type>(this->get_io_service()).init_task();
- }
+ io_service_.init_task();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -139,454 +150,258 @@
   int register_descriptor(socket_type descriptor,
       per_descriptor_data& descriptor_data)
   {
- // No need to lock according to epoll documentation.
+ mutex::scoped_lock lock(registered_descriptors_mutex_);
 
- descriptor_data.allow_speculative_read = true;
- descriptor_data.allow_speculative_write = true;
+ descriptor_map::iterator new_entry = registered_descriptors_.insert(
+ std::make_pair(descriptor, descriptor_state())).first;
+ descriptor_data = &new_entry->second;
 
     epoll_event ev = { 0, { 0 } };
- ev.events = 0;
- ev.data.fd = descriptor;
+ ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.data.ptr = descriptor_data;
     int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
     if (result != 0)
       return errno;
- return 0;
- }
-
- // Start a new read operation. The handler object will be invoked when the
- // given descriptor is ready to be read, or an error has occurred.
- template <typename Handler>
- void start_read_op(socket_type descriptor,
- per_descriptor_data& descriptor_data,
- Handler handler, bool allow_speculative_read = true)
- {
- if (allow_speculative_read && descriptor_data.allow_speculative_read)
- {
- 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;
- }
-
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- if (shutdown_)
- return;
-
- if (!allow_speculative_read)
- need_epoll_wait_ = true;
- else if (!read_op_queue_.has_operation(descriptor))
- {
- // Speculative reads are ok as there are no queued read operations.
- descriptor_data.allow_speculative_read = true;
+ descriptor_data->shutdown_ = false;
 
- 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.
- descriptor_data.allow_speculative_read = false;
-
- if (read_op_queue_.enqueue_operation(descriptor, handler))
- {
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
- if (write_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLOUT;
- if (except_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLPRI;
- ev.data.fd = descriptor;
-
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0 && errno == ENOENT)
- result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
- if (result != 0)
- {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- read_op_queue_.perform_all_operations(descriptor, ec);
- }
- }
+ return 0;
   }
 
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready to be written, or an error has occurred.
- template <typename Handler>
- void start_write_op(socket_type descriptor,
+ // Start a new operation. The reactor operation will be performed when the
+ // given descriptor is flagged as ready, or an error has occurred.
+ void start_op(int op_type, socket_type descriptor,
       per_descriptor_data& descriptor_data,
- Handler handler, bool allow_speculative_write = true)
+ reactor_op* op, bool allow_speculative)
   {
- if (allow_speculative_write && descriptor_data.allow_speculative_write)
- {
- 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;
- }
-
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
+ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+ if (descriptor_data->shutdown_)
       return;
 
- if (!allow_speculative_write)
- need_epoll_wait_ = true;
- else if (!write_op_queue_.has_operation(descriptor))
+ if (descriptor_data->op_queue_[op_type].empty())
     {
- // Speculative writes are ok as there are no queued write operations.
- descriptor_data.allow_speculative_write = true;
-
- boost::system::error_code ec;
- std::size_t bytes_transferred = 0;
- if (handler.perform(ec, bytes_transferred))
+ if (allow_speculative)
       {
- handler.complete(ec, bytes_transferred);
- return;
- }
- }
-
- // Speculative writes are not ok as there will be queued write operations.
- descriptor_data.allow_speculative_write = false;
-
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
- if (read_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLIN;
- if (except_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLPRI;
- ev.data.fd = descriptor;
-
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0 && errno == ENOENT)
- result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
- if (result != 0)
- {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, ec);
+ if (op->perform())
+ {
+ descriptor_lock.unlock();
+ io_service_.post_immediate_completion(op);
+ return;
+ }
       }
- }
- }
-
- // Start a new exception operation. The handler object will be invoked when
- // the given descriptor has exception information, or an error has occurred.
- template <typename Handler>
- void start_except_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (except_op_queue_.enqueue_operation(descriptor, handler))
- {
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP;
- if (read_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLIN;
- if (write_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLOUT;
- ev.data.fd = descriptor;
-
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0 && errno == ENOENT)
- result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
- if (result != 0)
+ else
       {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- except_op_queue_.perform_all_operations(descriptor, ec);
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
+ | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.data.ptr = descriptor_data;
+ epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
       }
     }
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready for writing or an error has occurred. Speculative
- // writes are not allowed.
- template <typename Handler>
- void start_connect_op(socket_type descriptor,
- per_descriptor_data& descriptor_data, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- if (shutdown_)
- return;
-
- // Speculative writes are not ok as there will be queued write operations.
- descriptor_data.allow_speculative_write = false;
-
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
- if (read_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLIN;
- if (except_op_queue_.has_operation(descriptor))
- ev.events |= EPOLLPRI;
- ev.data.fd = descriptor;
-
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0 && errno == ENOENT)
- result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
- if (result != 0)
- {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, ec);
- }
- }
+ descriptor_data->op_queue_[op_type].push(op);
+ io_service_.work_started();
   }
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
- void cancel_ops(socket_type descriptor, per_descriptor_data&)
+ void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- cancel_ops_unlocked(descriptor);
+ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
+ ops.push(descriptor_data->op_queue_[i]);
+
+ descriptor_lock.unlock();
+
+ io_service_.post_deferred_completions(ops);
   }
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
- void close_descriptor(socket_type descriptor, per_descriptor_data&)
+ void close_descriptor(socket_type descriptor,
+ per_descriptor_data& descriptor_data)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+ mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
 
- // Remove the descriptor from epoll.
- epoll_event ev = { 0, { 0 } };
- epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
+ // 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)
+ ops.push(descriptor_data->op_queue_[i]);
+
+ descriptor_lock.unlock();
 
- // Cancel any outstanding operations associated with the descriptor.
- cancel_ops_unlocked(descriptor);
+ registered_descriptors_.erase(descriptor);
+
+ descriptors_lock.unlock();
+
+ io_service_.post_deferred_completions(ops);
   }
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
   void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- timer_queues_.push_back(&timer_queue);
+ mutex::scoped_lock lock(mutex_);
+ timer_queues_.insert(&timer_queue);
   }
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- if (timer_queues_[i] == &timer_queue)
- {
- timer_queues_.erase(timer_queues_.begin() + i);
- return;
- }
- }
+ mutex::scoped_lock lock(mutex_);
+ timer_queues_.erase(&timer_queue);
   }
 
- // Schedule a timer in the given timer queue to expire at the specified
- // absolute time. The handler object will be invoked when the timer expires.
- template <typename Time_Traits, typename Handler>
+ // 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, Handler handler, void* token)
+ const typename Time_Traits::time_type& time, timer_op* op, void* token)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
- if (timer_queue.enqueue_timer(time, handler, token))
+ {
+ bool earliest = timer_queue.enqueue_timer(time, op, token);
+ io_service_.work_started();
+ if (earliest)
+ {
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ if (timer_fd_ != -1)
+ {
+ itimerspec new_timeout;
+ itimerspec old_timeout;
+ int flags = get_timeout(new_timeout);
+ timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+ return;
+ }
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
         interrupter_.interrupt();
+ }
+ }
   }
 
- // Cancel the timer associated with the given token. Returns the number of
- // handlers that have been posted or dispatched.
+ // 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)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- std::size_t n = timer_queue.cancel_timer(token);
- if (n > 0)
- interrupter_.interrupt();
+ mutex::scoped_lock lock(mutex_);
+ op_queue<operation> ops;
+ std::size_t n = timer_queue.cancel_timer(token, ops);
+ lock.unlock();
+ io_service_.post_deferred_completions(ops);
     return n;
   }
 
-private:
- friend class task_io_service<epoll_reactor<Own_Thread> >;
-
   // Run epoll once until interrupted or events are ready to be dispatched.
- void run(bool block)
+ void run(bool block, op_queue<operation>& ops)
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- // Dispatch any operation cancellations that were made while the select
- // loop was not running.
- 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_)
- {
- complete_operations_and_timers(lock);
- return;
- }
-
- // We can return immediately if there's no work to do and the reactor is
- // not supposed to block.
- if (!block && read_op_queue_.empty() && write_op_queue_.empty()
- && except_op_queue_.empty() && all_timer_queues_are_empty())
+ // Calculate a timeout only if timerfd is not used.
+ int timeout;
+ if (timer_fd_ != -1)
+ timeout = block ? -1 : 0;
+ else
     {
- complete_operations_and_timers(lock);
- return;
+ mutex::scoped_lock lock(mutex_);
+ timeout = block ? get_timeout() : 0;
     }
 
- int timeout = block ? get_timeout() : 0;
- wait_in_progress_ = true;
- lock.unlock();
-
     // Block on the epoll descriptor.
     epoll_event events[128];
- int num_events = (block || need_epoll_wait_)
- ? epoll_wait(epoll_fd_, events, 128, timeout)
- : 0;
+ int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
 
- lock.lock();
- wait_in_progress_ = false;
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ bool check_timers = (timer_fd_ == -1);
+#else // defined(BOOST_ASIO_HAS_TIMERFD)
+ bool check_timers = true;
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
 
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
     {
- int descriptor = events[i].data.fd;
- if (descriptor == interrupter_.read_descriptor())
+ void* ptr = events[i].data.ptr;
+ if (ptr == &interrupter_)
       {
- interrupter_.reset();
+ // No need to reset the interrupter since we're leaving the descriptor
+ // in a ready-to-read state and relying on edge-triggered notifications
+ // to make it so that we only get woken up when the descriptor's epoll
+ // registration is updated.
+
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ if (timer_fd_ == -1)
+ check_timers = true;
+#else // defined(BOOST_ASIO_HAS_TIMERFD)
+ check_timers = true;
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
       }
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ else if (ptr == &timer_fd_)
+ {
+ check_timers = true;
+ }
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
       else
       {
- bool more_reads = false;
- bool more_writes = false;
- bool more_except = false;
- boost::system::error_code ec;
+ descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
 
         // 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_.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_.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_.perform_operation(descriptor, ec);
- else
- more_writes = write_op_queue_.has_operation(descriptor);
-
- if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0
- && (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0
- && !more_except && !more_reads && !more_writes)
+ static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
+ for (int j = max_ops - 1; j >= 0; --j)
         {
- // If we have an event and no operations associated with the
- // descriptor then we need to delete the descriptor from epoll. The
- // epoll_wait system call can produce EPOLLHUP or EPOLLERR events
- // when there is no operation pending, so if we do not remove the
- // descriptor we can end up in a tight loop of repeated
- // calls to epoll_wait.
- epoll_event ev = { 0, { 0 } };
- epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
- }
- else
- {
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLERR | EPOLLHUP;
- if (more_reads)
- ev.events |= EPOLLIN;
- if (more_writes)
- ev.events |= EPOLLOUT;
- if (more_except)
- ev.events |= EPOLLPRI;
- ev.data.fd = descriptor;
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0 && errno == ENOENT)
- result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
- if (result != 0)
+ if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
           {
- ec = boost::system::error_code(errno,
- boost::asio::error::get_system_category());
- read_op_queue_.perform_all_operations(descriptor, ec);
- write_op_queue_.perform_all_operations(descriptor, ec);
- except_op_queue_.perform_all_operations(descriptor, ec);
+ while (reactor_op* op = descriptor_data->op_queue_[j].front())
+ {
+ if (op->perform())
+ {
+ descriptor_data->op_queue_[j].pop();
+ ops.push(op);
+ }
+ else
+ break;
+ }
           }
         }
       }
     }
- 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();
- timer_queues_[i]->dispatch_cancellations();
- }
-
- // Issue any pending cancellations.
- for (size_t i = 0; i < pending_cancellations_.size(); ++i)
- cancel_ops_unlocked(pending_cancellations_[i]);
- pending_cancellations_.clear();
 
- // Determine whether epoll_wait should be called when the reactor next runs.
- need_epoll_wait_ = !read_op_queue_.empty()
- || !write_op_queue_.empty() || !except_op_queue_.empty();
-
- complete_operations_and_timers(lock);
- }
-
- // Run the select loop in the thread.
- void run_thread()
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- while (!stop_thread_)
+ if (check_timers)
     {
- lock.unlock();
- run(true);
- lock.lock();
- }
- }
+ mutex::scoped_lock common_lock(mutex_);
+ timer_queues_.get_ready_timers(ops);
 
- // Entry point for the select loop thread.
- static void call_run_thread(epoll_reactor* reactor)
- {
- reactor->run_thread();
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ if (timer_fd_ != -1)
+ {
+ itimerspec new_timeout;
+ itimerspec old_timeout;
+ int flags = get_timeout(new_timeout);
+ timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+ }
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
+ }
   }
 
   // Interrupt the select loop.
   void interrupt()
   {
- interrupter_.interrupt();
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+ ev.data.ptr = &interrupter_;
+ epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
   }
 
+private:
   // The hint to pass to epoll_create to size its data structures.
   enum { epoll_size = 20000 };
 
@@ -606,117 +421,65 @@
     return fd;
   }
 
- // Check if all timer queues are empty.
- bool all_timer_queues_are_empty() const
- {
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- if (!timer_queues_[i]->empty())
- return false;
- return true;
- }
-
   // Get the timeout value for the epoll_wait call. The timeout value is
   // returned as a number of milliseconds. A return value of -1 indicates
   // that epoll_wait should block indefinitely.
   int get_timeout()
   {
- if (all_timer_queues_are_empty())
- return -1;
-
     // By default we will wait no longer than 5 minutes. This will ensure that
     // any changes to the system clock are detected after no longer than this.
- boost::posix_time::time_duration minimum_wait_duration
- = boost::posix_time::minutes(5);
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- boost::posix_time::time_duration wait_duration
- = timer_queues_[i]->wait_duration();
- if (wait_duration < minimum_wait_duration)
- minimum_wait_duration = wait_duration;
- }
-
- if (minimum_wait_duration > boost::posix_time::time_duration())
- {
- int milliseconds = minimum_wait_duration.total_milliseconds();
- return milliseconds > 0 ? milliseconds : 1;
- }
- else
- {
- return 0;
- }
+ return timer_queues_.wait_duration_msec(5 * 60 * 1000);
   }
 
- // Cancel all operations associated with the given descriptor. The do_cancel
- // function of the handler objects will be invoked. This function does not
- // acquire the epoll_reactor's mutex.
- void cancel_ops_unlocked(socket_type descriptor)
- {
- bool interrupt = read_op_queue_.cancel_operations(descriptor);
- interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
- interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
- if (interrupt)
- interrupter_.interrupt();
- }
-
- // Clean up operations and timers. We must not hold the lock since the
- // 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 complete_operations_and_timers(
- boost::asio::detail::mutex::scoped_lock& lock)
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+ // Get the timeout value for the timer descriptor. The return value is the
+ // flag argument to be used when calling timerfd_settime.
+ int get_timeout(itimerspec& ts)
   {
- timer_queues_for_cleanup_ = timer_queues_;
- lock.unlock();
- 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]->complete_timers();
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+
+ long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+ ts.it_value.tv_sec = usec / 1000000;
+ ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
+
+ return usec ? 0 : TFD_TIMER_ABSTIME;
   }
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
+
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_;
 
   // Mutex to protect access to internal data.
- boost::asio::detail::mutex mutex_;
+ mutex mutex_;
 
   // The epoll file descriptor.
   int epoll_fd_;
 
- // Whether the epoll_wait call is currently in progress
- bool wait_in_progress_;
+ // The timer file descriptor.
+ int timer_fd_;
 
   // The interrupter is used to break a blocking epoll_wait call.
   select_interrupter interrupter_;
 
- // The queue of read operations.
- reactor_op_queue<socket_type> read_op_queue_;
-
- // The queue of write operations.
- reactor_op_queue<socket_type> write_op_queue_;
-
- // The queue of except operations.
- reactor_op_queue<socket_type> except_op_queue_;
-
   // The timer queues.
- std::vector<timer_queue_base*> timer_queues_;
-
- // A copy of the timer queues, used when cleaning up timers. The copy is
- // stored as a class data member to avoid unnecessary memory allocation.
- std::vector<timer_queue_base*> timer_queues_for_cleanup_;
-
- // The descriptors that are pending cancellation.
- std::vector<socket_type> pending_cancellations_;
-
- // Does the reactor loop thread need to stop.
- bool stop_thread_;
-
- // The thread that is running the reactor loop.
- boost::asio::detail::thread* thread_;
+ timer_queue_set timer_queues_;
 
   // Whether the service has been shut down.
   bool shutdown_;
 
- // Whether we need to call epoll_wait the next time the reactor is run.
- bool need_epoll_wait_;
+ // 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_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/epoll_reactor_fwd.hpp
==============================================================================
--- branches/release/boost/asio/detail/epoll_reactor_fwd.hpp (original)
+++ branches/release/boost/asio/detail/epoll_reactor_fwd.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -33,7 +33,6 @@
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class epoll_reactor;
 
 } // namespace detail

Deleted: branches/release/boost/asio/detail/handler_base_from_member.hpp
==============================================================================
--- branches/release/boost/asio/detail/handler_base_from_member.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
+++ (empty file)
@@ -1,78 +0,0 @@
-//
-// handler_base_from_member.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_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

Deleted: branches/release/boost/asio/detail/handler_queue.hpp
==============================================================================
--- branches/release/boost/asio/detail/handler_queue.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
+++ (empty file)
@@ -1,231 +0,0 @@
-//
-// handler_queue.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_HANDLER_QUEUE_HPP
-#define BOOST_ASIO_DETAIL_HANDLER_QUEUE_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>
-#include <boost/asio/detail/noncopyable.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-class handler_queue
- : private noncopyable
-{
-public:
- // Base class for handlers in the queue.
- class handler
- : private noncopyable
- {
- public:
- void invoke()
- {
- invoke_func_(this);
- }
-
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- typedef void (*invoke_func_type)(handler*);
- typedef void (*destroy_func_type)(handler*);
-
- handler(invoke_func_type invoke_func,
- destroy_func_type destroy_func)
- : next_(0),
- invoke_func_(invoke_func),
- destroy_func_(destroy_func)
- {
- }
-
- ~handler()
- {
- }
-
- private:
- friend class handler_queue;
- handler* next_;
- invoke_func_type invoke_func_;
- destroy_func_type destroy_func_;
- };
-
- // Smart point to manager handler lifetimes.
- class scoped_ptr
- : private noncopyable
- {
- public:
- explicit scoped_ptr(handler* h)
- : handler_(h)
- {
- }
-
- ~scoped_ptr()
- {
- if (handler_)
- handler_->destroy();
- }
-
- handler* get() const
- {
- return handler_;
- }
-
- handler* release()
- {
- handler* tmp = handler_;
- handler_ = 0;
- return tmp;
- }
-
- private:
- handler* handler_;
- };
-
- // Constructor.
- handler_queue()
- : front_(0),
- back_(0)
- {
- }
-
- // Wrap a handler to be pushed into the queue.
- template <typename Handler>
- static handler* wrap(Handler h)
- {
- // Allocate and construct an object to wrap the handler.
- typedef handler_wrapper<Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(h);
- handler_ptr<alloc_traits> ptr(raw_ptr, h);
- return ptr.release();
- }
-
- // Get the handler at the front of the queue.
- handler* front()
- {
- return front_;
- }
-
- // Pop a handler from the front of the queue.
- void pop()
- {
- if (front_)
- {
- handler* tmp = front_;
- front_ = front_->next_;
- if (front_ == 0)
- back_ = 0;
- tmp->next_= 0;
- }
- }
-
- // Push a handler on to the back of the queue.
- void push(handler* h)
- {
- h->next_ = 0;
- if (back_)
- {
- back_->next_ = h;
- back_ = h;
- }
- else
- {
- front_ = back_ = h;
- }
- }
-
- // Whether the queue is empty.
- bool empty() const
- {
- return front_ == 0;
- }
-
-private:
- // Template wrapper for handlers.
- template <typename Handler>
- class handler_wrapper
- : public handler
- {
- public:
- handler_wrapper(Handler h)
- : handler(
- &handler_wrapper<Handler>::do_call,
- &handler_wrapper<Handler>::do_destroy),
- handler_(h)
- {
- }
-
- static void do_call(handler* base)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(h->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
-
- static void do_destroy(handler* base)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(h->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
-
- private:
- Handler handler_;
- };
-
- // The front of the queue.
- handler* front_;
-
- // The back of the queue.
- handler* back_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP

Modified: branches/release/boost/asio/detail/hash_map.hpp
==============================================================================
--- branches/release/boost/asio/detail/hash_map.hpp (original)
+++ branches/release/boost/asio/detail/hash_map.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -21,7 +21,6 @@
 #include <cassert>
 #include <list>
 #include <utility>
-#include <vector>
 #include <boost/functional/hash.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
@@ -62,9 +61,16 @@
 
   // Constructor.
   hash_map()
- : size_(0)
+ : size_(0),
+ buckets_(0),
+ num_buckets_(0)
   {
- rehash(hash_size(0));
+ }
+
+ // Destructor.
+ ~hash_map()
+ {
+ delete[] buckets_;
   }
 
   // Get an iterator for the beginning of the map.
@@ -100,17 +106,20 @@
   // Find an entry in the map.
   iterator find(const K& k)
   {
- size_t bucket = calculate_hash_value(k) % buckets_.size();
- iterator it = buckets_[bucket].first;
- if (it == values_.end())
- return values_.end();
- iterator end = buckets_[bucket].last;
- ++end;
- while (it != end)
+ if (num_buckets_)
     {
- if (it->first == k)
- return it;
- ++it;
+ size_t bucket = calculate_hash_value(k) % num_buckets_;
+ iterator it = buckets_[bucket].first;
+ if (it == values_.end())
+ return values_.end();
+ iterator end = buckets_[bucket].last;
+ ++end;
+ while (it != end)
+ {
+ if (it->first == k)
+ return it;
+ ++it;
+ }
     }
     return values_.end();
   }
@@ -118,17 +127,20 @@
   // Find an entry in the map.
   const_iterator find(const K& k) const
   {
- size_t bucket = calculate_hash_value(k) % buckets_.size();
- const_iterator it = buckets_[bucket].first;
- if (it == values_.end())
- return it;
- const_iterator end = buckets_[bucket].last;
- ++end;
- while (it != end)
+ if (num_buckets_)
     {
- if (it->first == k)
+ size_t bucket = calculate_hash_value(k) % num_buckets_;
+ const_iterator it = buckets_[bucket].first;
+ if (it == values_.end())
         return it;
- ++it;
+ const_iterator end = buckets_[bucket].last;
+ ++end;
+ while (it != end)
+ {
+ if (it->first == k)
+ return it;
+ ++it;
+ }
     }
     return values_.end();
   }
@@ -136,9 +148,9 @@
   // Insert a new entry into the map.
   std::pair<iterator, bool> insert(const value_type& v)
   {
- if (size_ + 1 >= buckets_.size())
+ if (size_ + 1 >= num_buckets_)
       rehash(hash_size(size_ + 1));
- size_t bucket = calculate_hash_value(v.first) % buckets_.size();
+ size_t bucket = calculate_hash_value(v.first) % num_buckets_;
     iterator it = buckets_[bucket].first;
     if (it == values_.end())
     {
@@ -165,7 +177,7 @@
   {
     assert(it != values_.end());
 
- size_t bucket = calculate_hash_value(it->first) % buckets_.size();
+ size_t bucket = calculate_hash_value(it->first) % num_buckets_;
     bool is_first = (it == buckets_[bucket].first);
     bool is_last = (it == buckets_[bucket].last);
     if (is_first && is_last)
@@ -179,6 +191,14 @@
     --size_;
   }
 
+ // Erase a key from the map.
+ void erase(const K& k)
+ {
+ iterator it = find(k);
+ if (it != values_.end())
+ erase(it);
+ }
+
   // Remove all entries from the map.
   void clear()
   {
@@ -187,8 +207,9 @@
     size_ = 0;
 
     // Initialise all buckets to empty.
- for (size_t i = 0; i < buckets_.size(); ++i)
- buckets_[i].first = buckets_[i].last = values_.end();
+ iterator end = values_.end();
+ for (size_t i = 0; i < num_buckets_; ++i)
+ buckets_[i].first = buckets_[i].last = end;
   }
 
 private:
@@ -215,21 +236,24 @@
   // Re-initialise the hash from the values already contained in the list.
   void rehash(std::size_t num_buckets)
   {
- if (num_buckets == buckets_.size())
+ if (num_buckets == num_buckets_)
       return;
+ num_buckets_ = num_buckets;
 
     iterator end = values_.end();
 
     // Update number of buckets and initialise all buckets to empty.
- buckets_.resize(num_buckets);
- for (std::size_t i = 0; i < buckets_.size(); ++i)
+ bucket_type* tmp = new bucket_type[num_buckets_];
+ delete[] buckets_;
+ buckets_ = tmp;
+ for (std::size_t i = 0; i < num_buckets_; ++i)
       buckets_[i].first = buckets_[i].last = end;
 
     // Put all values back into the hash.
     iterator iter = values_.begin();
     while (iter != end)
     {
- std::size_t bucket = calculate_hash_value(iter->first) % buckets_.size();
+ std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_;
       if (buckets_[bucket].last == end)
       {
         buckets_[bucket].first = buckets_[bucket].last = iter++;
@@ -282,14 +306,15 @@
   // The type for a bucket in the hash table.
   struct bucket_type
   {
- bucket_type() {}
- bucket_type(const bucket_type&) { /* noop */ }
     iterator first;
     iterator last;
   };
 
   // The buckets in the hash.
- std::vector<bucket_type> buckets_;
+ bucket_type* buckets_;
+
+ // The number of buckets in the hash.
+ std::size_t num_buckets_;
 };
 
 } // namespace detail

Deleted: branches/release/boost/asio/detail/indirect_handler_queue.hpp
==============================================================================
--- branches/release/boost/asio/detail/indirect_handler_queue.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
+++ (empty file)
@@ -1,293 +0,0 @@
-//
-// indirect_handler_queue.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_INDIRECT_HANDLER_QUEUE_HPP
-#define BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_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>
-#include <boost/asio/detail/noncopyable.hpp>
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1310)
-extern "C" void _ReadWriteBarrier();
-# pragma intrinsic(_ReadWriteBarrier)
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1310)
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-class indirect_handler_queue
- : private noncopyable
-{
-public:
- class handler;
-
- // Element for a node in the queue.
- class node
- {
- public:
- node()
- : version_(0),
- handler_(0),
- next_(0)
- {
- }
-
- private:
- friend class indirect_handler_queue;
- unsigned long version_;
- handler* handler_;
- node* next_;
- };
-
- // Base class for handlers in the queue.
- class handler
- : private noncopyable
- {
- public:
- void invoke()
- {
- invoke_func_(this);
- }
-
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- typedef void (*invoke_func_type)(handler*);
- typedef void (*destroy_func_type)(handler*);
-
- handler(invoke_func_type invoke_func,
- destroy_func_type destroy_func)
- : node_(new node),
- invoke_func_(invoke_func),
- destroy_func_(destroy_func)
- {
- }
-
- ~handler()
- {
- if (node_)
- delete node_;
- }
-
- private:
- friend class indirect_handler_queue;
- node* node_;
- invoke_func_type invoke_func_;
- destroy_func_type destroy_func_;
- };
-
- // Smart point to manager handler lifetimes.
- class scoped_ptr
- : private noncopyable
- {
- public:
- explicit scoped_ptr(handler* h)
- : handler_(h)
- {
- }
-
- ~scoped_ptr()
- {
- if (handler_)
- handler_->destroy();
- }
-
- handler* get() const
- {
- return handler_;
- }
-
- handler* release()
- {
- handler* tmp = handler_;
- handler_ = 0;
- return tmp;
- }
-
- private:
- handler* handler_;
- };
-
- // Constructor.
- indirect_handler_queue()
- : front_(new node),
- back_(front_),
- next_version_(1)
- {
- }
-
- // Destructor.
- ~indirect_handler_queue()
- {
- while (front_)
- {
- node* tmp = front_;
- front_ = front_->next_;
- delete tmp;
- }
- }
-
- // Wrap a handler to be pushed into the queue.
- template <typename Handler>
- static handler* wrap(Handler h)
- {
- // Allocate and construct an object to wrap the handler.
- typedef handler_wrapper<Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(h);
- handler_ptr<alloc_traits> ptr(raw_ptr, h);
- return ptr.release();
- }
-
- // Determine whether the queue has something ready to pop.
- bool poppable()
- {
- return front_->next_ != 0;
- }
-
- // The version number at the front of the queue.
- unsigned long front_version()
- {
- return front_->version_;
- }
-
- // The version number at the back of the queue.
- unsigned long back_version()
- {
- return back_->version_;
- }
-
- // Pop a handler from the front of the queue.
- handler* pop()
- {
- node* n = front_;
- node* new_front = n->next_;
- if (new_front)
- {
- handler* h = new_front->handler_;
- h->node_ = n;
- new_front->handler_ = 0;
- front_ = new_front;
- return h;
- }
- return 0;
- }
-
- // Push a handler on to the back of the queue.
- void push(handler* h)
- {
- node* n = h->node_;
- h->node_ = 0;
- n->version_ = next_version_;
- next_version_ += 2;
- n->handler_ = h;
- n->next_ = 0;
- memory_barrier();
- back_->next_ = n;
- back_ = n;
- }
-
-private:
- // Template wrapper for handlers.
- template <typename Handler>
- class handler_wrapper
- : public handler
- {
- public:
- handler_wrapper(Handler h)
- : handler(
- &handler_wrapper<Handler>::do_call,
- &handler_wrapper<Handler>::do_destroy),
- handler_(h)
- {
- }
-
- static void do_call(handler* base)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(h->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
-
- static void do_destroy(handler* base)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(h->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
-
- private:
- Handler handler_;
- };
-
- // Helper function to create a memory barrier.
- static void memory_barrier()
- {
-#if defined(_GLIBCXX_WRITE_MEM_BARRIER)
- _GLIBCXX_WRITE_MEM_BARRIER;
-#elif defined(_MSC_VER) && (_MSC_VER >= 1310)
- _ReadWriteBarrier();
-#else
-# error memory barrier required
-#endif
- }
-
- // The front of the queue.
- node* front_;
-
- // The back of the queue.
- node* back_;
-
- // The next version counter to be assigned to a node.
- unsigned long next_version_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP

Modified: branches/release/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/kqueue_reactor.hpp (original)
+++ branches/release/boost/asio/detail/kqueue_reactor.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -24,28 +24,27 @@
 
 #include <boost/asio/detail/push_options.hpp>
 #include <cstddef>
-#include <vector>
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/time.h>
 #include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/system/system_error.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/task_io_service.hpp>
-#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/service_base.hpp>
-#include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/timer_queue_fwd.hpp>
+#include <boost/asio/detail/timer_queue_set.hpp>
 
 // Older versions of Mac OS X may not define EV_OOBAND.
 #if !defined(EV_OOBAND)
@@ -56,43 +55,29 @@
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class kqueue_reactor
- : public boost::asio::detail::service_base<kqueue_reactor<Own_Thread> >
+ : public boost::asio::detail::service_base<kqueue_reactor>
 {
 public:
+ enum { read_op = 0, write_op = 1,
+ connect_op = 1, except_op = 2, max_ops = 3 };
+
   // Per-descriptor data.
   struct per_descriptor_data
   {
- bool allow_speculative_read;
- bool allow_speculative_write;
+ bool allow_speculative[max_ops];
   };
 
   // Constructor.
   kqueue_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- kqueue_reactor<Own_Thread> >(io_service),
+ : boost::asio::detail::service_base<kqueue_reactor>(io_service),
+ io_service_(use_service<io_service_impl>(io_service)),
       mutex_(),
       kqueue_fd_(do_kqueue_create()),
- wait_in_progress_(false),
       interrupter_(),
- read_op_queue_(),
- write_op_queue_(),
- except_op_queue_(),
- pending_cancellations_(),
- stop_thread_(false),
- thread_(0),
       shutdown_(false),
       need_kqueue_wait_(true)
   {
- // Start the reactor's internal thread only if needed.
- if (Own_Thread)
- {
- boost::asio::detail::signal_blocker sb;
- thread_ = new boost::asio::detail::thread(
- bind_handler(&kqueue_reactor::call_run_thread, this));
- }
-
     // Add the interrupter's descriptor to the kqueue.
     struct kevent event;
     EV_SET(&event, interrupter_.read_descriptor(),
@@ -112,65 +97,49 @@
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     shutdown_ = true;
- stop_thread_ = true;
     lock.unlock();
 
- if (thread_)
- {
- interrupter_.interrupt();
- thread_->join();
- delete thread_;
- thread_ = 0;
- }
+ op_queue<operation> ops;
 
- read_op_queue_.destroy_operations();
- write_op_queue_.destroy_operations();
- except_op_queue_.destroy_operations();
+ for (int i = 0; i < max_ops; ++i)
+ op_queue_[i].get_all_operations(ops);
 
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- timer_queues_[i]->destroy_timers();
- timer_queues_.clear();
+ timer_queues_.get_all_timers(ops);
   }
 
- // Initialise the task, but only if the reactor is not in its own thread.
+ // Initialise the task.
   void init_task()
   {
- if (!Own_Thread)
- {
- typedef task_io_service<kqueue_reactor<Own_Thread> > task_io_service_type;
- use_service<task_io_service_type>(this->get_io_service()).init_task();
- }
+ io_service_.init_task();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
   int register_descriptor(socket_type, per_descriptor_data& descriptor_data)
   {
- descriptor_data.allow_speculative_read = true;
- descriptor_data.allow_speculative_write = true;
+ descriptor_data.allow_speculative[read_op] = true;
+ descriptor_data.allow_speculative[write_op] = true;
+ descriptor_data.allow_speculative[except_op] = true;
 
     return 0;
   }
 
- // Start a new read operation. The handler object will be invoked when the
- // given descriptor is ready to be read, or an error has occurred.
- template <typename Handler>
- void start_read_op(socket_type descriptor,
- per_descriptor_data& descriptor_data, Handler handler,
- bool allow_speculative_read = true)
+ // Start a new operation. The reactor operation will be performed when the
+ // given descriptor is flagged as ready, or an error has occurred.
+ void start_op(int op_type, socket_type descriptor,
+ per_descriptor_data& descriptor_data,
+ reactor_op* op, bool allow_speculative)
   {
- if (allow_speculative_read && descriptor_data.allow_speculative_read)
+ if (allow_speculative && descriptor_data.allow_speculative[op_type])
     {
- boost::system::error_code ec;
- std::size_t bytes_transferred = 0;
- if (handler.perform(ec, bytes_transferred))
+ if (op->perform())
       {
- handler.complete(ec, bytes_transferred);
+ io_service_.post_immediate_completion(op);
         return;
       }
 
       // We only get one shot at a speculative read in this function.
- allow_speculative_read = false;
+ allow_speculative = false;
     }
 
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
@@ -178,146 +147,49 @@
     if (shutdown_)
       return;
 
- if (!allow_speculative_read)
+ if (!allow_speculative)
       need_kqueue_wait_ = true;
- else if (!read_op_queue_.has_operation(descriptor))
+ else if (!op_queue_[op_type].has_operation(descriptor))
     {
       // Speculative reads are ok as there are no queued read operations.
- descriptor_data.allow_speculative_read = true;
+ descriptor_data.allow_speculative[op_type] = true;
 
- boost::system::error_code ec;
- std::size_t bytes_transferred = 0;
- if (handler.perform(ec, bytes_transferred))
+ if (op->perform())
       {
- handler.complete(ec, bytes_transferred);
+ lock.unlock();
+ io_service_.post_immediate_completion(op);
         return;
       }
     }
 
     // Speculative reads are not ok as there will be queued read operations.
- descriptor_data.allow_speculative_read = false;
+ descriptor_data.allow_speculative[op_type] = false;
 
- if (read_op_queue_.enqueue_operation(descriptor, handler))
+ bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+ io_service_.work_started();
+ if (first)
     {
       struct kevent event;
- EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
- if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ switch (op_type)
       {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- read_op_queue_.perform_all_operations(descriptor, ec);
- }
- }
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready to be written, or an error has occurred.
- template <typename Handler>
- void start_write_op(socket_type descriptor,
- per_descriptor_data& descriptor_data, Handler handler,
- bool allow_speculative_write = true)
- {
- if (allow_speculative_write && descriptor_data.allow_speculative_write)
- {
- 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;
- }
-
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (!allow_speculative_write)
- need_kqueue_wait_ = true;
- else if (!write_op_queue_.has_operation(descriptor))
- {
- // Speculative writes are ok as there are no queued write operations.
- descriptor_data.allow_speculative_write = true;
-
- 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.
- descriptor_data.allow_speculative_write = false;
-
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- struct kevent event;
- EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
- if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
- {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, ec);
- }
- }
- }
-
- // Start a new exception operation. The handler object will be invoked when
- // the given descriptor has exception information, or an error has occurred.
- template <typename Handler>
- void start_except_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- if (except_op_queue_.enqueue_operation(descriptor, handler))
- {
- struct kevent event;
- if (read_op_queue_.has_operation(descriptor))
+ case read_op:
         EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
- else
- EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
- if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
- {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- except_op_queue_.perform_all_operations(descriptor, ec);
+ break;
+ case write_op:
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
+ break;
+ case except_op:
+ if (op_queue_[read_op].has_operation(descriptor))
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
+ else
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, EV_OOBAND, 0, 0);
+ break;
       }
- }
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready to be written, or an error has occurred.
- template <typename Handler>
- void start_connect_op(socket_type descriptor,
- per_descriptor_data& descriptor_data, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (shutdown_)
- return;
-
- // Speculative writes are not ok as there will be queued write operations.
- descriptor_data.allow_speculative_write = false;
-
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- {
- struct kevent event;
- EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
       if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
       {
         boost::system::error_code ec(errno,
             boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, ec);
+ cancel_ops_unlocked(descriptor, ec);
       }
     }
   }
@@ -328,7 +200,7 @@
   void cancel_ops(socket_type descriptor, per_descriptor_data&)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- cancel_ops_unlocked(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Cancel any operations that are running against the descriptor and remove
@@ -344,7 +216,7 @@
     ::kevent(kqueue_fd_, event, 2, 0, 0, 0);
     
     // Cancel any outstanding operations associated with the descriptor.
- cancel_ops_unlocked(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Add a new timer queue to the reactor.
@@ -352,7 +224,7 @@
   void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- timer_queues_.push_back(&timer_queue);
+ timer_queues_.insert(&timer_queue);
   }
 
   // Remove a timer queue from the reactor.
@@ -360,77 +232,53 @@
   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- if (timer_queues_[i] == &timer_queue)
- {
- timer_queues_.erase(timer_queues_.begin() + i);
- return;
- }
- }
+ timer_queues_.erase(&timer_queue);
   }
 
- // Schedule a timer in the given timer queue to expire at the specified
- // absolute time. The handler object will be invoked when the timer expires.
- template <typename Time_Traits, typename Handler>
+ // 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, Handler handler, void* token)
+ const typename Time_Traits::time_type& time, timer_op* op, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
- if (timer_queue.enqueue_timer(time, handler, token))
+ {
+ bool earliest = timer_queue.enqueue_timer(time, op, token);
+ io_service_.work_started();
+ if (earliest)
         interrupter_.interrupt();
+ }
   }
 
- // Cancel the timer associated with the given token. Returns the number of
- // handlers that have been posted or dispatched.
+ // 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)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- std::size_t n = timer_queue.cancel_timer(token);
- if (n > 0)
- interrupter_.interrupt();
+ op_queue<operation> ops;
+ std::size_t n = timer_queue.cancel_timer(token, ops);
+ lock.unlock();
+ io_service_.post_deferred_completions(ops);
     return n;
   }
 
-private:
- friend class task_io_service<kqueue_reactor<Own_Thread> >;
-
   // Run the kqueue loop.
- void run(bool block)
+ void run(bool block, op_queue<operation>& ops)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- // Dispatch any operation cancellations that were made while the select
- // loop was not running.
- 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_)
- {
- complete_operations_and_timers(lock);
- return;
- }
-
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
- if (!block && read_op_queue_.empty() && write_op_queue_.empty()
- && except_op_queue_.empty() && all_timer_queues_are_empty())
- {
- complete_operations_and_timers(lock);
+ if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+ && op_queue_[except_op].empty() && timer_queues_.all_empty())
       return;
- }
 
     // Determine how long to block while waiting for events.
     timespec timeout_buf = { 0, 0 };
     timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
 
- wait_in_progress_ = true;
     lock.unlock();
 
     // Block on the kqueue descriptor.
@@ -440,7 +288,6 @@
       : 0;
 
     lock.lock();
- wait_in_progress_ = false;
 
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
@@ -459,23 +306,22 @@
         {
           boost::system::error_code error(
               events[i].data, boost::asio::error::get_system_category());
- except_op_queue_.perform_all_operations(descriptor, error);
- read_op_queue_.perform_all_operations(descriptor, error);
+ op_queue_[except_op].perform_operations(descriptor, ops);
+ op_queue_[read_op].perform_operations(descriptor, ops);
         }
         else if (events[i].flags & EV_OOBAND)
         {
- boost::system::error_code error;
- more_except = except_op_queue_.perform_operation(descriptor, error);
+ more_except
+ = op_queue_[except_op].perform_operations(descriptor, ops);
           if (events[i].data > 0)
- more_reads = read_op_queue_.perform_operation(descriptor, error);
+ more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
           else
- more_reads = read_op_queue_.has_operation(descriptor);
+ more_reads = op_queue_[read_op].has_operation(descriptor);
         }
         else
         {
- boost::system::error_code error;
- more_reads = read_op_queue_.perform_operation(descriptor, error);
- more_except = except_op_queue_.has_operation(descriptor);
+ more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
+ more_except = op_queue_[except_op].has_operation(descriptor);
         }
 
         // Update the descriptor in the kqueue.
@@ -490,8 +336,8 @@
         {
           boost::system::error_code error(errno,
               boost::asio::error::get_system_category());
- except_op_queue_.perform_all_operations(descriptor, error);
- read_op_queue_.perform_all_operations(descriptor, error);
+ op_queue_[except_op].cancel_operations(descriptor, ops, error);
+ op_queue_[read_op].cancel_operations(descriptor, ops, error);
         }
       }
       else if (events[i].filter == EVFILT_WRITE)
@@ -502,12 +348,11 @@
         {
           boost::system::error_code error(
               events[i].data, boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, error);
+ op_queue_[write_op].cancel_operations(descriptor, ops, error);
         }
         else
         {
- boost::system::error_code error;
- more_writes = write_op_queue_.perform_operation(descriptor, error);
+ more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
         }
 
         // Update the descriptor in the kqueue.
@@ -520,48 +365,15 @@
         {
           boost::system::error_code error(errno,
               boost::asio::error::get_system_category());
- write_op_queue_.perform_all_operations(descriptor, error);
+ op_queue_[write_op].cancel_operations(descriptor, ops, error);
         }
       }
     }
-
- 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();
- timer_queues_[i]->dispatch_cancellations();
- }
-
- // Issue any pending cancellations.
- for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
- cancel_ops_unlocked(pending_cancellations_[i]);
- pending_cancellations_.clear();
+ timer_queues_.get_ready_timers(ops);
 
     // Determine whether kqueue needs to be called next time the reactor is run.
- need_kqueue_wait_ = !read_op_queue_.empty()
- || !write_op_queue_.empty() || !except_op_queue_.empty();
-
- complete_operations_and_timers(lock);
- }
-
- // Run the select loop in the thread.
- void run_thread()
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- while (!stop_thread_)
- {
- lock.unlock();
- run(true);
- lock.lock();
- }
- }
-
- // Entry point for the select loop thread.
- static void call_run_thread(kqueue_reactor* reactor)
- {
- reactor->run_thread();
+ need_kqueue_wait_ = !op_queue_[read_op].empty()
+ || !op_queue_[write_op].empty() || !op_queue_[except_op].empty();
   }
 
   // Interrupt the select loop.
@@ -570,6 +382,7 @@
     interrupter_.interrupt();
   }
 
+private:
   // Create the kqueue file descriptor. Throws an exception if the descriptor
   // cannot be created.
   static int do_kqueue_create()
@@ -586,112 +399,45 @@
     return fd;
   }
 
- // Check if all timer queues are empty.
- bool all_timer_queues_are_empty() const
- {
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- if (!timer_queues_[i]->empty())
- return false;
- return true;
- }
-
   // Get the timeout value for the kevent call.
   timespec* get_timeout(timespec& ts)
   {
- if (all_timer_queues_are_empty())
- return 0;
-
     // By default we will wait no longer than 5 minutes. This will ensure that
     // any changes to the system clock are detected after no longer than this.
- boost::posix_time::time_duration minimum_wait_duration
- = boost::posix_time::minutes(5);
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- boost::posix_time::time_duration wait_duration
- = timer_queues_[i]->wait_duration();
- if (wait_duration < minimum_wait_duration)
- minimum_wait_duration = wait_duration;
- }
-
- if (minimum_wait_duration > boost::posix_time::time_duration())
- {
- ts.tv_sec = minimum_wait_duration.total_seconds();
- ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000;
- }
- else
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- }
-
+ long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+ ts.tv_sec = usec / 1000000;
+ ts.tv_nsec = (usec % 1000000) * 1000;
     return &ts;
   }
 
- // Cancel all operations associated with the given descriptor. The do_cancel
- // function of the handler objects will be invoked. This function does not
- // acquire the kqueue_reactor's mutex.
- void cancel_ops_unlocked(socket_type descriptor)
- {
- bool interrupt = read_op_queue_.cancel_operations(descriptor);
- interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
- interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
- if (interrupt)
- interrupter_.interrupt();
- }
-
- // Clean up operations and timers. We must not hold the lock since the
- // 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 complete_operations_and_timers(
- boost::asio::detail::mutex::scoped_lock& lock)
- {
- timer_queues_for_cleanup_ = timer_queues_;
- lock.unlock();
- 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]->complete_timers();
+ // Cancel all operations associated with the given descriptor. This function
+ // does not acquire the kqueue_reactor's mutex.
+ void cancel_ops_unlocked(socket_type descriptor,
+ const boost::system::error_code& ec)
+ {
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
+ op_queue_[i].cancel_operations(descriptor, ops, ec);
+ io_service_.post_deferred_completions(ops);
   }
 
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_;
+
   // Mutex to protect access to internal data.
   boost::asio::detail::mutex mutex_;
 
   // The kqueue file descriptor.
   int kqueue_fd_;
 
- // Whether the kqueue wait call is currently in progress
- bool wait_in_progress_;
-
   // The interrupter is used to break a blocking kevent call.
   select_interrupter interrupter_;
 
- // The queue of read operations.
- reactor_op_queue<socket_type> read_op_queue_;
-
- // The queue of write operations.
- reactor_op_queue<socket_type> write_op_queue_;
-
- // The queue of except operations.
- reactor_op_queue<socket_type> except_op_queue_;
+ // The queues of read, write and except operations.
+ reactor_op_queue<socket_type> op_queue_[max_ops];
 
   // The timer queues.
- std::vector<timer_queue_base*> timer_queues_;
-
- // A copy of the timer queues, used when cleaning up timers. The copy is
- // stored as a class data member to avoid unnecessary memory allocation.
- std::vector<timer_queue_base*> timer_queues_for_cleanup_;
-
- // The descriptors that are pending cancellation.
- std::vector<socket_type> pending_cancellations_;
-
- // Does the reactor loop thread need to stop.
- bool stop_thread_;
-
- // The thread that is running the reactor loop.
- boost::asio::detail::thread* thread_;
+ timer_queue_set timer_queues_;
 
   // Whether the service has been shut down.
   bool shutdown_;

Modified: branches/release/boost/asio/detail/kqueue_reactor_fwd.hpp
==============================================================================
--- branches/release/boost/asio/detail/kqueue_reactor_fwd.hpp (original)
+++ branches/release/boost/asio/detail/kqueue_reactor_fwd.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -30,7 +30,6 @@
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class kqueue_reactor;
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/null_event.hpp
==============================================================================
--- branches/release/boost/asio/detail/null_event.hpp (original)
+++ branches/release/boost/asio/detail/null_event.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -49,6 +49,12 @@
   {
   }
 
+ // Signal the event and unlock the mutex.
+ template <typename Lock>
+ void signal_and_unlock(Lock&)
+ {
+ }
+
   // Reset the event.
   template <typename Lock>
   void clear(Lock&)

Modified: branches/release/boost/asio/detail/posix_event.hpp
==============================================================================
--- branches/release/boost/asio/detail/posix_event.hpp (original)
+++ branches/release/boost/asio/detail/posix_event.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -72,6 +72,16 @@
     ::pthread_cond_signal(&cond_); // Ignore EINVAL.
   }
 
+ // Signal the event and unlock the mutex.
+ template <typename Lock>
+ void signal_and_unlock(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ signalled_ = true;
+ lock.unlock();
+ ::pthread_cond_signal(&cond_); // Ignore EINVAL.
+ }
+
   // Reset the event.
   template <typename Lock>
   void clear(Lock& lock)

Modified: branches/release/boost/asio/detail/posix_mutex.hpp
==============================================================================
--- branches/release/boost/asio/detail/posix_mutex.hpp (original)
+++ branches/release/boost/asio/detail/posix_mutex.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -62,35 +62,19 @@
   // Destructor.
   ~posix_mutex()
   {
- ::pthread_mutex_destroy(&mutex_);
+ ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY.
   }
 
   // Lock the mutex.
   void lock()
   {
- int error = ::pthread_mutex_lock(&mutex_);
- if (error != 0)
- {
- boost::system::system_error e(
- boost::system::error_code(error,
- boost::asio::error::get_system_category()),
- "mutex");
- boost::throw_exception(e);
- }
+ (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.
   }
 
   // Unlock the mutex.
   void unlock()
   {
- int error = ::pthread_mutex_unlock(&mutex_);
- if (error != 0)
- {
- boost::system::system_error e(
- boost::system::error_code(error,
- boost::asio::error::get_system_category()),
- "mutex");
- boost::throw_exception(e);
- }
+ (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.
   }
 
 private:

Modified: branches/release/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactive_descriptor_service.hpp (original)
+++ branches/release/boost/asio/detail/reactive_descriptor_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -21,10 +21,13 @@
 #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/buffer_sequence_adapter.hpp>
 #include <boost/asio/detail/descriptor_ops.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/null_buffers_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 
 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
@@ -32,10 +35,7 @@
 namespace asio {
 namespace detail {
 
-template <typename Reactor>
 class reactive_descriptor_service
- : public boost::asio::detail::service_base<
- reactive_descriptor_service<Reactor> >
 {
 public:
   // The native type of a descriptor.
@@ -55,22 +55,28 @@
 
   private:
     // Only this service will have access to the internal values.
- friend class reactive_descriptor_service<Reactor>;
+ friend class reactive_descriptor_service;
 
     // The native descriptor representation.
     int descriptor_;
 
     enum
     {
- user_set_non_blocking = 1, // The user wants a non-blocking descriptor.
- internal_non_blocking = 2 // The descriptor has been set non-blocking.
+ // The user wants a non-blocking descriptor.
+ user_set_non_blocking = 1,
+
+ // The descriptor has been set non-blocking.
+ internal_non_blocking = 2,
+
+ // Helper "flag" used to determine whether the socket is non-blocking.
+ non_blocking = user_set_non_blocking | internal_non_blocking
     };
 
     // Flags indicating the current state of the descriptor.
     unsigned char flags_;
 
     // Per-descriptor data used by the reactor.
- typename Reactor::per_descriptor_data reactor_data_;
+ reactor::per_descriptor_data reactor_data_;
   };
 
   // The maximum number of buffers to support in a single operation.
@@ -78,9 +84,8 @@
 
   // Constructor.
   reactive_descriptor_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- reactive_descriptor_service<Reactor> >(io_service),
- reactor_(boost::asio::use_service<Reactor>(io_service))
+ : io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)),
+ reactor_(boost::asio::use_service<reactor>(io_service))
   {
     reactor_.init_task();
   }
@@ -236,47 +241,22 @@
       return 0;
     }
 
- // Copy buffers into array.
- descriptor_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- descriptor_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
     // A request to read_some 0 bytes on a stream is a no-op.
- if (total_buffer_size == 0)
+ if (bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
     }
 
- // Make descriptor non-blocking if user wants non-blocking.
- if (impl.flags_ & implementation_type::user_set_non_blocking)
- {
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- if (descriptor_ops::ioctl(impl.descriptor_,
- FIONBIO, &non_blocking, ec))
- return 0;
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
- }
-
     // Send the data.
     for (;;)
     {
       // Try to complete the operation without blocking.
       int bytes_sent = descriptor_ops::gather_write(
- impl.descriptor_, bufs, i, ec);
+ impl.descriptor_, bufs.buffers(), bufs.count(), ec);
 
       // Check if operation succeeded.
       if (bytes_sent >= 0)
@@ -310,48 +290,31 @@
     return 0;
   }
 
- template <typename ConstBufferSequence, typename Handler>
- class write_operation :
- public handler_base_from_member<Handler>
+ template <typename ConstBufferSequence>
+ class write_op_base : public reactor_op
   {
   public:
- write_operation(int descriptor, boost::asio::io_service& io_service,
- const ConstBufferSequence& buffers, Handler handler)
- : handler_base_from_member<Handler>(handler),
+ write_op_base(int descriptor,
+ const ConstBufferSequence& buffers, func_type complete_func)
+ : reactor_op(&write_op_base::do_perform, complete_func),
         descriptor_(descriptor),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ write_op_base* o(static_cast<write_op_base*>(base));
 
- // Copy buffers into array.
- descriptor_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers_.begin();
- typename ConstBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- descriptor_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Write the data.
- int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec);
+ boost::system::error_code ec;
+ int bytes = descriptor_ops::gather_write(
+ o->descriptor_, bufs.buffers(), bufs.count(), ec);
 
         // Retry operation if interrupted by signal.
         if (ec == boost::asio::error::interrupted)
@@ -362,120 +325,89 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->ec_ = ec;
+ o->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_;
   };
 
- // Start an asynchronous write. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
- void async_write_some(implementation_type& impl,
- const ConstBufferSequence& buffers, Handler handler)
- {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Determine total size of buffers.
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
-
- // A request to read_some 0 bytes on a stream is a no-op.
- if (total_buffer_size == 0)
- {
- this->get_io_service().post(bind_handler(handler,
- boost::system::error_code(), 0));
- return;
- }
-
- // Make descriptor non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec, 0));
- return;
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
-
- reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
- write_operation<ConstBufferSequence, Handler>(
- impl.descriptor_, this->get_io_service(), buffers, handler));
- }
- }
-
- template <typename Handler>
- class null_buffers_operation :
- public handler_base_from_member<Handler>
+ class write_op : public write_op_base<ConstBufferSequence>
   {
   public:
- null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
- : handler_base_from_member<Handler>(handler),
- work_(io_service)
- {
- }
-
- bool perform(boost::system::error_code&,
- std::size_t& bytes_transferred)
+ write_op(int descriptor,
+ const ConstBufferSequence& buffers, Handler handler)
+ : write_op_base<ConstBufferSequence>(
+ descriptor, buffers, &write_op::do_complete),
+ handler_(handler)
     {
- 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));
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ write_op* o(static_cast<write_op*>(base));
+ typedef handler_alloc_traits<Handler, write_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   private:
- boost::asio::io_service::work work_;
+ Handler handler_;
   };
 
+ // Start an asynchronous write. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef write_op<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.descriptor_, buffers, handler);
+
+ start_op(impl, reactor::write_op, ptr.get(), true,
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers));
+ ptr.release();
+ }
+
   // Start an asynchronous wait until data can be written without blocking.
   template <typename Handler>
   void async_write_some(implementation_type& impl,
       const null_buffers&, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ start_op(impl, reactor::write_op, ptr.get(), false, false);
+ ptr.release();
   }
 
   // Read some data from the stream. Returns the number of bytes read.
@@ -489,46 +421,22 @@
       return 0;
     }
 
- // Copy buffers into array.
- descriptor_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- descriptor_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
     // A request to read_some 0 bytes on a stream is a no-op.
- if (total_buffer_size == 0)
+ if (bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
     }
 
- // Make descriptor non-blocking if user wants non-blocking.
- if (impl.flags_ & implementation_type::user_set_non_blocking)
- {
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
- return 0;
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
- }
-
     // Read some data.
     for (;;)
     {
       // Try to complete the operation without blocking.
       int bytes_read = descriptor_ops::scatter_read(
- impl.descriptor_, bufs, i, ec);
+ impl.descriptor_, bufs.buffers(), bufs.count(), ec);
 
       // Check if operation succeeded.
       if (bytes_read > 0)
@@ -569,48 +477,31 @@
     return 0;
   }
 
- template <typename MutableBufferSequence, typename Handler>
- class read_operation :
- public handler_base_from_member<Handler>
+ template <typename MutableBufferSequence>
+ class read_op_base : public reactor_op
   {
   public:
- read_operation(int descriptor, boost::asio::io_service& io_service,
- const MutableBufferSequence& buffers, Handler handler)
- : handler_base_from_member<Handler>(handler),
+ read_op_base(int descriptor,
+ const MutableBufferSequence& buffers, func_type complete_func)
+ : reactor_op(&read_op_base::do_perform, complete_func),
         descriptor_(descriptor),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ read_op_base* o(static_cast<read_op_base*>(base));
 
- // Copy buffers into array.
- descriptor_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers_.begin();
- typename MutableBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- descriptor_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Read some data.
- int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec);
+ boost::system::error_code ec;
+ int bytes = descriptor_ops::scatter_read(
+ o->descriptor_, bufs.buffers(), bufs.count(), ec);
         if (bytes == 0)
           ec = boost::asio::error::eof;
 
@@ -623,22 +514,56 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->ec_ = ec;
+ o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
         return true;
       }
     }
 
- void complete(const boost::system::error_code& ec,
- std::size_t bytes_transferred)
+ private:
+ int descriptor_;
+ MutableBufferSequence buffers_;
+ };
+
+ template <typename MutableBufferSequence, typename Handler>
+ class read_op : public read_op_base<MutableBufferSequence>
+ {
+ public:
+ read_op(int descriptor,
+ const MutableBufferSequence& buffers, Handler handler)
+ : read_op_base<MutableBufferSequence>(
+ descriptor, buffers, &read_op::do_complete),
+ handler_(handler)
     {
- io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ read_op* o(static_cast<read_op*>(base));
+ typedef handler_alloc_traits<Handler, read_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   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
@@ -647,72 +572,79 @@
   void async_read_some(implementation_type& impl,
       const MutableBufferSequence& buffers, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Determine total size of buffers.
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef read_op<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ impl.descriptor_, buffers, handler);
+
+ start_op(impl, reactor::read_op, ptr.get(), true,
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers));
+ ptr.release();
+ }
 
- // A request to read_some 0 bytes on a stream is a no-op.
- if (total_buffer_size == 0)
- {
- this->get_io_service().post(bind_handler(handler,
- boost::system::error_code(), 0));
- return;
- }
+ // Wait until data can be read without blocking.
+ template <typename Handler>
+ void async_read_some(implementation_type& impl,
+ const null_buffers&, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- // Make descriptor non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ start_op(impl, reactor::read_op, ptr.get(), false, false);
+ ptr.release();
+ }
+
+private:
+ // Start the asynchronous operation.
+ void start_op(implementation_type& impl, int op_type,
+ reactor_op* op, bool non_blocking, bool noop)
+ {
+ if (!noop)
+ {
+ if (is_open(impl))
       {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+ if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
         {
- this->get_io_service().post(bind_handler(handler, ec, 0));
+ reactor_.start_op(op_type, impl.descriptor_,
+ impl.reactor_data_, op, non_blocking);
           return;
         }
- impl.flags_ |= implementation_type::internal_non_blocking;
       }
-
- reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
- read_operation<MutableBufferSequence, Handler>(
- impl.descriptor_, this->get_io_service(), buffers, handler));
+ else
+ op->ec_ = boost::asio::error::bad_descriptor;
     }
+
+ io_service_impl_.post_immediate_completion(op);
   }
 
- // Wait until data can be read without blocking.
- template <typename Handler>
- void async_read_some(implementation_type& impl,
- const null_buffers&, Handler handler)
+ // Determine whether the descriptor has been set non-blocking.
+ bool is_non_blocking(implementation_type& impl) const
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ return (impl.flags_ & implementation_type::non_blocking);
   }
 
-private:
+ // Set the internal non-blocking flag.
+ bool set_non_blocking(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+ return false;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ return true;
+ }
+
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_impl_;
+
   // The selector that performs event demultiplexing for the service.
- Reactor& reactor_;
+ reactor& reactor_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/reactive_serial_port_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactive_serial_port_service.hpp (original)
+++ branches/release/boost/asio/detail/reactive_serial_port_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -38,31 +38,24 @@
 namespace detail {
 
 // Extend reactive_descriptor_service to provide serial port support.
-template <typename Reactor>
 class reactive_serial_port_service
- : public boost::asio::detail::service_base<
- reactive_serial_port_service<Reactor> >
 {
 public:
- // The native type of a stream handle.
- typedef typename reactive_descriptor_service<Reactor>::native_type
- native_type;
-
- // The implementation type of the stream handle.
- typedef typename reactive_descriptor_service<Reactor>::implementation_type
- implementation_type;
+ // The native type of a serial port.
+ typedef reactive_descriptor_service::native_type native_type;
+
+ // The implementation type of the serial port.
+ typedef reactive_descriptor_service::implementation_type implementation_type;
 
   reactive_serial_port_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- reactive_serial_port_service>(io_service),
- descriptor_service_(boost::asio::use_service<
- reactive_descriptor_service<Reactor> >(io_service))
+ : descriptor_service_(io_service)
   {
   }
 
   // Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ descriptor_service_.shutdown_service();
   }
 
   // Construct a new handle implementation.
@@ -254,8 +247,8 @@
   }
 
 private:
- // The handle service used for initiating asynchronous operations.
- reactive_descriptor_service<Reactor>& descriptor_service_;
+ // The implementation used for initiating asynchronous operations.
+ reactive_descriptor_service descriptor_service_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactive_socket_service.hpp (original)
+++ branches/release/boost/asio/detail/reactive_socket_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -17,18 +17,17 @@
 
 #include <boost/asio/detail/push_options.hpp>
 
-#include <boost/asio/detail/push_options.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/asio/detail/pop_options.hpp>
-
 #include <boost/asio/buffer.hpp>
 #include <boost/asio/error.hpp>
 #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/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/null_buffers_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/socket_holder.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
@@ -37,10 +36,8 @@
 namespace asio {
 namespace detail {
 
-template <typename Protocol, typename Reactor>
+template <typename Protocol>
 class reactive_socket_service
- : public boost::asio::detail::service_base<
- reactive_socket_service<Protocol, Reactor> >
 {
 public:
   // The protocol type.
@@ -67,7 +64,7 @@
 
   private:
     // Only this service will have access to the internal values.
- friend class reactive_socket_service<Protocol, Reactor>;
+ friend class reactive_socket_service<Protocol>;
 
     // The native socket representation.
     socket_type socket_;
@@ -87,7 +84,7 @@
       // User wants connection_aborted errors, which are disabled by default.
       enable_connection_aborted = 4,
 
- // The user set the linger option. Needs to be checked when closing.
+ // The user set the linger option. Needs to be checked when closing.
       user_set_linger = 8
     };
 
@@ -98,17 +95,13 @@
     protocol_type protocol_;
 
     // Per-descriptor data used by the reactor.
- typename Reactor::per_descriptor_data reactor_data_;
+ reactor::per_descriptor_data reactor_data_;
   };
 
- // The maximum number of buffers to support in a single operation.
- enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
-
   // Constructor.
   reactive_socket_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- reactive_socket_service<Protocol, Reactor> >(io_service),
- reactor_(boost::asio::use_service<Reactor>(io_service))
+ : io_service_impl_(use_service<io_service_impl>(io_service)),
+ reactor_(use_service<reactor>(io_service))
   {
     reactor_.init_task();
   }
@@ -553,23 +546,11 @@
       return 0;
     }
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
     // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
@@ -579,7 +560,8 @@
     for (;;)
     {
       // Try to complete the operation without blocking.
- int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec);
+ int bytes_sent = socket_ops::send(impl.socket_,
+ bufs.buffers(), bufs.count(), flags, ec);
 
       // Check if operation succeeded.
       if (bytes_sent >= 0)
@@ -613,50 +595,32 @@
     return 0;
   }
 
- template <typename ConstBufferSequence, typename Handler>
- class send_operation :
- public handler_base_from_member<Handler>
+ template <typename ConstBufferSequence>
+ class send_op_base : public reactor_op
   {
   public:
- send_operation(socket_type socket, boost::asio::io_service& io_service,
- const ConstBufferSequence& buffers, socket_base::message_flags flags,
- Handler handler)
- : handler_base_from_member<Handler>(handler),
+ send_op_base(socket_type socket, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&send_op_base::do_perform, complete_func),
         socket_(socket),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers),
         flags_(flags)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ send_op_base* o(static_cast<send_op_base*>(base));
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers_.begin();
- typename ConstBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Send the data.
- int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
+ boost::system::error_code ec;
+ int bytes = socket_ops::send(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_, ec);
 
         // Retry operation if interrupted by signal.
         if (ec == boost::asio::error::interrupted)
@@ -667,127 +631,92 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->ec_ = ec;
+ o->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_;
   };
 
- // Start an asynchronous send. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
- void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- if (impl.protocol_.type() == SOCK_STREAM)
- {
- // Determine total size of buffers.
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (total_buffer_size == 0)
- {
- this->get_io_service().post(bind_handler(handler,
- boost::system::error_code(), 0));
- return;
- }
- }
-
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- if (!(impl.flags_ & implementation_type::non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec, 0));
- return;
- }
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
-
- reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- send_operation<ConstBufferSequence, Handler>(
- impl.socket_, this->get_io_service(), buffers, flags, handler));
- }
- }
-
- template <typename Handler>
- class null_buffers_operation :
- public handler_base_from_member<Handler>
+ class send_op : public send_op_base<ConstBufferSequence>
   {
   public:
- null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
- : handler_base_from_member<Handler>(handler),
- work_(io_service)
- {
- }
-
- bool perform(boost::system::error_code&,
- std::size_t& bytes_transferred)
+ send_op(socket_type socket, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ : send_op_base<ConstBufferSequence>(socket,
+ buffers, flags, &send_op::do_complete),
+ handler_(handler)
     {
- 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));
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ send_op* o(static_cast<send_op*>(base));
+ typedef handler_alloc_traits<Handler, send_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   private:
- boost::asio::io_service::work work_;
+ Handler handler_;
   };
 
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef send_op<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ impl.socket_, buffers, flags, handler);
+
+ start_op(impl, reactor::write_op, ptr.get(), true,
+ (impl.protocol_.type() == SOCK_STREAM
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ ptr.release();
+ }
+
   // Start an asynchronous wait until data can be sent without blocking.
   template <typename Handler>
   void async_send(implementation_type& impl, const null_buffers&,
       socket_base::message_flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ start_op(impl, reactor::write_op, ptr.get(), false, false);
+ ptr.release();
   }
 
   // Send a datagram to the specified endpoint. Returns the number of bytes
@@ -803,25 +732,15 @@
       return 0;
     }
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
     // Send the data.
     for (;;)
     {
       // Try to complete the operation without blocking.
- int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags,
- destination.data(), destination.size(), ec);
+ int bytes_sent = socket_ops::sendto(impl.socket_, bufs.buffers(),
+ bufs.count(), flags, destination.data(), destination.size(), ec);
 
       // Check if operation succeeded.
       if (bytes_sent >= 0)
@@ -856,52 +775,34 @@
     return 0;
   }
 
- template <typename ConstBufferSequence, typename Handler>
- class send_to_operation :
- public handler_base_from_member<Handler>
+ template <typename ConstBufferSequence>
+ class send_to_op_base : public reactor_op
   {
   public:
- 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)
- : handler_base_from_member<Handler>(handler),
+ send_to_op_base(socket_type socket, const ConstBufferSequence& buffers,
+ const endpoint_type& endpoint, socket_base::message_flags flags,
+ func_type complete_func)
+ : reactor_op(&send_to_op_base::do_perform, complete_func),
         socket_(socket),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers),
         destination_(endpoint),
         flags_(flags)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ send_to_op_base* o(static_cast<send_to_op_base*>(base));
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers_.begin();
- typename ConstBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<const void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Send the data.
- int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
- destination_.data(), destination_.size(), ec);
+ boost::system::error_code ec;
+ int bytes = socket_ops::sendto(o->socket_, bufs.buffers(), bufs.count(),
+ o->flags_, o->destination_.data(), o->destination_.size(), ec);
 
         // Retry operation if interrupted by signal.
         if (ec == boost::asio::error::interrupted)
@@ -912,26 +813,61 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->ec_ = ec;
+ o->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_;
     endpoint_type destination_;
     socket_base::message_flags flags_;
   };
 
+ template <typename ConstBufferSequence, typename Handler>
+ class send_to_op : public send_to_op_base<ConstBufferSequence>
+ {
+ public:
+ send_to_op(socket_type socket, const ConstBufferSequence& buffers,
+ const endpoint_type& endpoint, socket_base::message_flags flags,
+ Handler handler)
+ : send_to_op_base<ConstBufferSequence>(socket,
+ buffers, endpoint, flags, &send_to_op::do_complete),
+ handler_(handler)
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ send_to_op* o(static_cast<send_to_op*>(base));
+ typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
+ }
+
+ private:
+ Handler handler_;
+ };
+
   // Start an asynchronous send. The data being sent must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
@@ -940,34 +876,15 @@
       const endpoint_type& destination, socket_base::message_flags flags,
       Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- if (!(impl.flags_ & implementation_type::non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec, 0));
- return;
- }
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef send_to_op<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
+ buffers, destination, flags, handler);
 
- reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- send_to_operation<ConstBufferSequence, Handler>(
- impl.socket_, this->get_io_service(), buffers,
- destination, flags, handler));
- }
+ start_op(impl, reactor::write_op, ptr.get(), true, false);
+ ptr.release();
   }
 
   // Start an asynchronous wait until data can be sent without blocking.
@@ -975,17 +892,14 @@
   void async_send_to(implementation_type& impl, const null_buffers&,
       socket_base::message_flags, const endpoint_type&, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- reactor_.start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ start_op(impl, reactor::write_op, ptr.get(), false, false);
+ ptr.release();
   }
 
   // Receive some data from the peer. Returns the number of bytes received.
@@ -1000,23 +914,11 @@
       return 0;
     }
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
     // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
@@ -1026,7 +928,8 @@
     for (;;)
     {
       // Try to complete the operation without blocking.
- int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec);
+ int bytes_recvd = socket_ops::recv(impl.socket_,
+ bufs.buffers(), bufs.count(), flags, ec);
 
       // Check if operation succeeded.
       if (bytes_recvd > 0)
@@ -1067,53 +970,35 @@
     return 0;
   }
 
- template <typename MutableBufferSequence, typename Handler>
- class receive_operation :
- public handler_base_from_member<Handler>
+ template <typename MutableBufferSequence>
+ class receive_op_base : public reactor_op
   {
   public:
- receive_operation(socket_type socket, int protocol_type,
- boost::asio::io_service& io_service,
+ receive_op_base(socket_type socket, int protocol_type,
         const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- : handler_base_from_member<Handler>(handler),
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&receive_op_base::do_perform, complete_func),
         socket_(socket),
         protocol_type_(protocol_type),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers),
         flags_(flags)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ receive_op_base* o(static_cast<receive_op_base*>(base));
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers_.begin();
- typename MutableBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Receive some data.
- int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
- if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ boost::system::error_code ec;
+ int bytes = socket_ops::recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_, ec);
+ if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
           ec = boost::asio::error::eof;
 
         // Retry operation if interrupted by signal.
@@ -1125,93 +1010,84 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->ec_ = ec;
+ o->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_;
     int protocol_type_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
     MutableBufferSequence buffers_;
     socket_base::message_flags flags_;
   };
 
- // Start an asynchronous receive. The buffer for the data being received
- // must be valid for the lifetime of the asynchronous operation.
   template <typename MutableBufferSequence, typename Handler>
- void async_receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
+ class receive_op : public receive_op_base<MutableBufferSequence>
   {
- if (!is_open(impl))
+ public:
+ receive_op(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ : receive_op_base<MutableBufferSequence>(socket,
+ protocol_type, buffers, flags, &receive_op::do_complete),
+ handler_(handler)
     {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
     }
- else
- {
- if (impl.protocol_.type() == SOCK_STREAM)
- {
- // Determine total size of buffers.
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
 
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (total_buffer_size == 0)
- {
- this->get_io_service().post(bind_handler(handler,
- boost::system::error_code(), 0));
- return;
- }
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ receive_op* o(static_cast<receive_op*>(base));
+ typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
       }
+ }
 
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- if (!(impl.flags_ & implementation_type::non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec, 0));
- return;
- }
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
+ private:
+ Handler handler_;
+ };
 
- if (flags & socket_base::message_out_of_band)
- {
- reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- receive_operation<MutableBufferSequence, Handler>(
- impl.socket_, impl.protocol_.type(),
- this->get_io_service(), buffers, flags, handler));
- }
- else
- {
- reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- receive_operation<MutableBufferSequence, Handler>(
- impl.socket_, impl.protocol_.type(),
- this->get_io_service(), buffers, flags, handler));
- }
- }
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef receive_op<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ int protocol_type = impl.protocol_.type();
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
+ protocol_type, buffers, flags, handler);
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get(), true,
+ (impl.protocol_.type() == SOCK_STREAM
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ ptr.release();
   }
 
   // Wait until data can be received without blocking.
@@ -1219,22 +1095,17 @@
   void async_receive(implementation_type& impl, const null_buffers&,
       socket_base::message_flags flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else if (flags & socket_base::message_out_of_band)
- {
- reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler));
- }
- else
- {
- reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get(), false, false);
+ ptr.release();
   }
 
   // Receive a datagram with the endpoint of the sender. Returns the number of
@@ -1251,26 +1122,16 @@
       return 0;
     }
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
     // Receive some data.
     for (;;)
     {
       // Try to complete the operation without blocking.
       std::size_t addr_len = sender_endpoint.capacity();
- int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
- sender_endpoint.data(), &addr_len, ec);
+ int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs.buffers(),
+ bufs.count(), flags, sender_endpoint.data(), &addr_len, ec);
 
       // Check if operation succeeded.
       if (bytes_recvd > 0)
@@ -1318,56 +1179,37 @@
     return 0;
   }
 
- template <typename MutableBufferSequence, typename Handler>
- class receive_from_operation :
- public handler_base_from_member<Handler>
+ template <typename MutableBufferSequence>
+ class receive_from_op_base : public reactor_op
   {
   public:
- receive_from_operation(socket_type socket, int protocol_type,
- boost::asio::io_service& io_service,
+ receive_from_op_base(socket_type socket, int protocol_type,
         const MutableBufferSequence& buffers, endpoint_type& endpoint,
- socket_base::message_flags flags, Handler handler)
- : handler_base_from_member<Handler>(handler),
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&receive_from_op_base::do_perform, complete_func),
         socket_(socket),
         protocol_type_(protocol_type),
- io_service_(io_service),
- work_(io_service),
         buffers_(buffers),
         sender_endpoint_(endpoint),
         flags_(flags)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- {
- bytes_transferred = 0;
- return true;
- }
+ receive_from_op_base* o(static_cast<receive_from_op_base*>(base));
 
- // Copy buffers into array.
- socket_ops::buf bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers_.begin();
- typename MutableBufferSequence::const_iterator end = buffers_.end();
- size_t i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- socket_ops::init_buf(bufs[i],
- boost::asio::buffer_cast<void*>(buffer),
- boost::asio::buffer_size(buffer));
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
 
       for (;;)
       {
         // Receive some data.
- std::size_t addr_len = sender_endpoint_.capacity();
- int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
- sender_endpoint_.data(), &addr_len, ec);
- if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ boost::system::error_code ec;
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ int bytes = socket_ops::recvfrom(o->socket_, bufs.buffers(),
+ bufs.count(), o->flags_, o->sender_endpoint_.data(), &addr_len, ec);
+ if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
           ec = boost::asio::error::eof;
 
         // Retry operation if interrupted by signal.
@@ -1379,28 +1221,63 @@
             || ec == boost::asio::error::try_again)
           return false;
 
- sender_endpoint_.resize(addr_len);
- bytes_transferred = (bytes < 0 ? 0 : bytes);
+ o->sender_endpoint_.resize(addr_len);
+ o->ec_ = ec;
+ o->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_;
     int protocol_type_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
     MutableBufferSequence buffers_;
     endpoint_type& sender_endpoint_;
     socket_base::message_flags flags_;
   };
 
+ template <typename MutableBufferSequence, typename Handler>
+ class receive_from_op : public receive_from_op_base<MutableBufferSequence>
+ {
+ public:
+ receive_from_op(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, endpoint_type& endpoint,
+ socket_base::message_flags flags, Handler handler)
+ : receive_from_op_base<MutableBufferSequence>(socket, protocol_type,
+ buffers, endpoint, flags, &receive_from_op::do_complete),
+ handler_(handler)
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ receive_from_op* o(static_cast<receive_from_op*>(base));
+ typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
+ }
+
+ private:
+ Handler handler_;
+ };
+
   // Start an asynchronous receive. The buffer for the data being received and
   // the sender_endpoint object must both be valid for the lifetime of the
   // asynchronous operation.
@@ -1409,34 +1286,19 @@
       const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- if (!(impl.flags_ & implementation_type::non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec, 0));
- return;
- }
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
-
- reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- receive_from_operation<MutableBufferSequence, Handler>(
- impl.socket_, impl.protocol_.type(), this->get_io_service(),
- buffers, sender_endpoint, flags, handler));
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef receive_from_op<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ int protocol_type = impl.protocol_.type();
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
+ protocol_type, buffers, sender_endpoint, flags, handler);
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get(), true, false);
+ ptr.release();
   }
 
   // Wait until data can be received without blocking.
@@ -1445,28 +1307,20 @@
       const null_buffers&, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Reset endpoint since it can be given no sensible value at this time.
- sender_endpoint = endpoint_type();
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- if (flags & socket_base::message_out_of_band)
- {
- reactor_.start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler));
- }
- else
- {
- reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
- }
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get(), false, false);
+ ptr.release();
   }
 
   // Accept a new connection.
@@ -1546,19 +1400,15 @@
     }
   }
 
- template <typename Socket, typename Handler>
- class accept_operation :
- public handler_base_from_member<Handler>
+ template <typename Socket>
+ class accept_op_base : public reactor_op
   {
   public:
- 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)
- : handler_base_from_member<Handler>(handler),
+ accept_op_base(socket_type socket, Socket& peer,
+ const protocol_type& protocol, endpoint_type* peer_endpoint,
+ bool enable_connection_aborted, func_type complete_func)
+ : reactor_op(&accept_op_base::do_perform, complete_func),
         socket_(socket),
- io_service_(io_service),
- work_(io_service),
         peer_(peer),
         protocol_(protocol),
         peer_endpoint_(peer_endpoint),
@@ -1566,27 +1416,25 @@
     {
     }
 
- bool perform(boost::system::error_code& ec, std::size_t&)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- return true;
+ accept_op_base* o(static_cast<accept_op_base*>(base));
 
       for (;;)
       {
         // Accept the waiting connection.
+ boost::system::error_code ec;
         socket_holder new_socket;
         std::size_t addr_len = 0;
- if (peer_endpoint_)
+ std::size_t* addr_len_p = 0;
+ socket_addr_type* addr = 0;
+ if (o->peer_endpoint_)
         {
- addr_len = peer_endpoint_->capacity();
- new_socket.reset(socket_ops::accept(socket_,
- peer_endpoint_->data(), &addr_len, ec));
- }
- else
- {
- new_socket.reset(socket_ops::accept(socket_, 0, 0, ec));
+ addr_len = o->peer_endpoint_->capacity();
+ addr_len_p = &addr_len;
+ addr = o->peer_endpoint_->data();
         }
+ new_socket.reset(socket_ops::accept(o->socket_, addr, addr_len_p, ec));
 
         // Retry operation if interrupted by signal.
         if (ec == boost::asio::error::interrupted)
@@ -1597,83 +1445,95 @@
             || ec == boost::asio::error::try_again)
           return false;
         if (ec == boost::asio::error::connection_aborted
- && !enable_connection_aborted_)
+ && !o->enable_connection_aborted_)
           return false;
 #if defined(EPROTO)
- if (ec.value() == EPROTO && !enable_connection_aborted_)
+ if (ec.value() == EPROTO && !o->enable_connection_aborted_)
           return false;
 #endif // defined(EPROTO)
 
         // Transfer ownership of the new socket to the peer object.
         if (!ec)
         {
- if (peer_endpoint_)
- peer_endpoint_->resize(addr_len);
- peer_.assign(protocol_, new_socket.get(), ec);
+ if (o->peer_endpoint_)
+ o->peer_endpoint_->resize(addr_len);
+ o->peer_.assign(o->protocol_, new_socket.get(), ec);
           if (!ec)
             new_socket.release();
         }
 
+ o->ec_ = 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_;
     Socket& peer_;
     protocol_type protocol_;
     endpoint_type* peer_endpoint_;
     bool enable_connection_aborted_;
   };
 
+ template <typename Socket, typename Handler>
+ class accept_op : public accept_op_base<Socket>
+ {
+ public:
+ accept_op(socket_type socket, Socket& peer, const protocol_type& protocol,
+ endpoint_type* peer_endpoint, bool enable_connection_aborted,
+ Handler handler)
+ : accept_op_base<Socket>(socket, peer, protocol, peer_endpoint,
+ enable_connection_aborted, &accept_op::do_complete),
+ handler_(handler)
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ accept_op* o(static_cast<accept_op*>(base));
+ typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder1<Handler, boost::system::error_code>
+ handler(o->handler_, o->ec_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
+ }
+
+ private:
+ Handler handler_;
+ };
+
   // Start an asynchronous accept. The peer and peer_endpoint objects
   // must be valid until the accept's handler is invoked.
   template <typename Socket, typename Handler>
   void async_accept(implementation_type& impl, Socket& peer,
       endpoint_type* peer_endpoint, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor));
- }
- else if (peer.is_open())
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::already_open));
- }
- else
- {
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
- {
- if (!(impl.flags_ & implementation_type::non_blocking))
- {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- {
- this->get_io_service().post(bind_handler(handler, ec));
- return;
- }
- }
- impl.flags_ |= implementation_type::internal_non_blocking;
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef accept_op<Socket, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ bool enable_connection_aborted =
+ (impl.flags_ & implementation_type::enable_connection_aborted) != 0;
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, peer,
+ impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
 
- reactor_.start_read_op(impl.socket_, impl.reactor_data_,
- accept_operation<Socket, Handler>(
- impl.socket_, this->get_io_service(),
- peer, impl.protocol_, peer_endpoint,
- (impl.flags_ & implementation_type::enable_connection_aborted) != 0,
- handler));
- }
+ start_accept_op(impl, ptr.get(), peer.is_open());
+ ptr.release();
   }
 
   // Connect the socket to the specified endpoint.
@@ -1713,53 +1573,77 @@
     return ec;
   }
 
- template <typename Handler>
- class connect_operation :
- public handler_base_from_member<Handler>
+ class connect_op_base : public reactor_op
   {
   public:
- connect_operation(socket_type socket,
- boost::asio::io_service& io_service, Handler handler)
- : handler_base_from_member<Handler>(handler),
- socket_(socket),
- io_service_(io_service),
- work_(io_service)
+ connect_op_base(socket_type socket, func_type complete_func)
+ : reactor_op(&connect_op_base::do_perform, complete_func),
+ socket_(socket)
     {
     }
 
- bool perform(boost::system::error_code& ec, std::size_t&)
+ static bool do_perform(reactor_op* base)
     {
- // Check whether the operation was successful.
- if (ec)
- return true;
+ connect_op_base* o(static_cast<connect_op_base*>(base));
 
       // Get the error code from the connect operation.
       int connect_error = 0;
       size_t connect_error_len = sizeof(connect_error);
- if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
- &connect_error, &connect_error_len, ec) == socket_error_retval)
+ if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
         return true;
 
       // The connection failed so the handler will be posted with an error code.
       if (connect_error)
       {
- ec = boost::system::error_code(connect_error,
+ o->ec_ = boost::system::error_code(connect_error,
             boost::asio::error::get_system_category());
- return true;
       }
 
       return true;
     }
 
- void complete(const boost::system::error_code& ec, std::size_t)
+ private:
+ socket_type socket_;
+ };
+
+ template <typename Handler>
+ class connect_op : public connect_op_base
+ {
+ public:
+ connect_op(socket_type socket, Handler handler)
+ : connect_op_base(socket, &connect_op::do_complete),
+ handler_(handler)
     {
- io_service_.post(bind_handler(this->handler_, ec));
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ connect_op* o(static_cast<connect_op*>(base));
+ typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder1<Handler, boost::system::error_code>
+ handler(o->handler_, o->ec_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   private:
- socket_type socket_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
+ Handler handler_;
   };
 
   // Start an asynchronous connect.
@@ -1767,59 +1651,103 @@
   void async_connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor));
- return;
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef connect_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, handler);
+
+ start_connect_op(impl, ptr.get(), peer_endpoint);
+ ptr.release();
+ }
 
- // Make socket non-blocking.
- if (!(impl.flags_ & implementation_type::internal_non_blocking))
+private:
+ // Start the asynchronous read or write operation.
+ void start_op(implementation_type& impl, int op_type,
+ reactor_op* op, bool non_blocking, bool noop)
+ {
+ if (!noop)
     {
- if (!(impl.flags_ & implementation_type::non_blocking))
+ if (is_open(impl))
       {
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ if (!non_blocking || is_non_blocking(impl)
+ || set_non_blocking(impl, op->ec_))
         {
- this->get_io_service().post(bind_handler(handler, ec));
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, non_blocking);
           return;
         }
       }
- impl.flags_ |= implementation_type::internal_non_blocking;
+ else
+ op->ec_ = boost::asio::error::bad_descriptor;
     }
 
- // Start the connect operation. The socket is already marked as non-blocking
- // so the connection will take place asynchronously.
- boost::system::error_code ec;
- if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
- peer_endpoint.size(), ec) == 0)
- {
- // The connect operation has finished successfully so we need to post the
- // handler immediately.
- this->get_io_service().post(bind_handler(handler,
- boost::system::error_code()));
- }
- else if (ec == boost::asio::error::in_progress
- || ec == boost::asio::error::would_block)
- {
- // 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_operation<Handler>(impl.socket_,
- this->get_io_service(), handler));
- }
+ io_service_impl_.post_immediate_completion(op);
+ }
+
+ // Start the asynchronous accept operation.
+ void start_accept_op(implementation_type& impl,
+ reactor_op* op, bool peer_is_open)
+ {
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, true, false);
     else
     {
- // The connect operation has failed, so post the handler immediately.
- this->get_io_service().post(bind_handler(handler, ec));
+ op->ec_ = boost::asio::error::already_open;
+ io_service_impl_.post_immediate_completion(op);
     }
   }
 
-private:
+ // Start the asynchronous connect operation.
+ void start_connect_op(implementation_type& impl,
+ reactor_op* op, const endpoint_type& peer_endpoint)
+ {
+ if (is_open(impl))
+ {
+ if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
+ peer_endpoint.size(), op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op,
+ impl.socket_, impl.reactor_data_, op, true);
+ return;
+ }
+ }
+ }
+ }
+ else
+ op->ec_ = boost::asio::error::bad_descriptor;
+
+ io_service_impl_.post_immediate_completion(op);
+ }
+
+ // Determine whether the socket has been set non-blocking.
+ bool is_non_blocking(implementation_type& impl) const
+ {
+ return (impl.flags_ & implementation_type::non_blocking);
+ }
+
+ // Set the internal non-blocking flag.
+ bool set_non_blocking(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return false;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ return true;
+ }
+
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_impl_;
+
   // The selector that performs event demultiplexing for the service.
- Reactor& reactor_;
+ reactor& reactor_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/reactor_op_queue.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactor_op_queue.hpp (original)
+++ branches/release/boost/asio/detail/reactor_op_queue.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -17,14 +17,11 @@
 
 #include <boost/asio/detail/push_options.hpp>
 
-#include <boost/asio/detail/push_options.hpp>
-#include <memory>
-#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>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 
 namespace boost {
 namespace asio {
@@ -37,39 +34,21 @@
 public:
   // Constructor.
   reactor_op_queue()
- : operations_(),
- cancelled_operations_(0),
- complete_operations_(0)
+ : operations_()
   {
   }
 
   // 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 Operation>
- bool enqueue_operation(Descriptor descriptor, Operation operation)
+ bool enqueue_operation(Descriptor descriptor, reactor_op* op)
   {
- // 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;
+ typedef typename operations_map::iterator iterator;
+ typedef typename operations_map::value_type value_type;
     std::pair<iterator, bool> entry =
- 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_ = ptr.release();
-
- return false;
+ operations_.insert(value_type(descriptor, operations()));
+ entry.first->second.op_queue_.push(op);
+ return entry.second;
   }
 
   // Cancel all operations associated with the descriptor. Any operations
@@ -77,16 +56,19 @@
   // 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)
+ bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
+ const boost::system::error_code& ec =
+ boost::asio::error::operation_aborted)
   {
- typename operation_map::iterator i = operations_.find(descriptor);
+ typename operations_map::iterator i = operations_.find(descriptor);
     if (i != operations_.end())
     {
- op_base* last_op = i->second;
- while (last_op->next_)
- last_op = last_op->next_;
- last_op->next_ = cancelled_operations_;
- cancelled_operations_ = i->second;
+ while (reactor_op* op = i->second.op_queue_.front())
+ {
+ op->ec_ = ec;
+ i->second.op_queue_.pop();
+ ops.push(op);
+ }
       operations_.erase(i);
       return true;
     }
@@ -106,79 +88,37 @@
     return operations_.find(descriptor) != operations_.end();
   }
 
- // Perform the first operation corresponding to the descriptor. Returns true
- // if there are more operations queued for the descriptor.
- bool perform_operation(Descriptor descriptor,
- const boost::system::error_code& result)
+ // Perform the operations corresponding to the descriptor. Returns true if
+ // there are still unfinished operations queued for the descriptor.
+ bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
   {
- typename operation_map::iterator i = operations_.find(descriptor);
+ typename operations_map::iterator i = operations_.find(descriptor);
     if (i != operations_.end())
     {
- op_base* this_op = i->second;
- i->second = this_op->next_;
- this_op->next_ = complete_operations_;
- complete_operations_ = this_op;
- bool done = this_op->perform(result);
- if (done)
+ while (reactor_op* op = i->second.op_queue_.front())
       {
- // Operation has finished.
- if (i->second)
+ if (op->perform())
         {
- return true;
+ i->second.op_queue_.pop();
+ ops.push(op);
         }
         else
         {
- operations_.erase(i);
- return false;
- }
- }
- else
- {
- // Operation wants to be called again. Leave it at the front of the
- // 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;
- }
- }
- return false;
- }
-
- // 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);
- if (i != operations_.end())
- {
- while (i->second)
- {
- op_base* this_op = i->second;
- i->second = this_op->next_;
- 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 completed list.
- complete_operations_ = this_op->next_;
- this_op->next_ = i->second;
- i->second = this_op;
- return;
+ return true;
         }
       }
       operations_.erase(i);
     }
+ return false;
   }
 
   // Fill a descriptor set with the descriptors corresponding to each active
- // operation.
+ // operation. The op_queue is used only when descriptors fail to be added to
+ // the descriptor set.
   template <typename Descriptor_Set>
- void get_descriptors(Descriptor_Set& descriptors)
+ void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops)
   {
- typename operation_map::iterator i = operations_.begin();
+ typename operations_map::iterator i = operations_.begin();
     while (i != operations_.end())
     {
       Descriptor descriptor = i->first;
@@ -186,7 +126,7 @@
       if (!descriptors.set(descriptor))
       {
         boost::system::error_code ec(error::fd_set_failure);
- perform_all_operations(descriptor, ec);
+ cancel_operations(descriptor, ops, ec);
       }
     }
   }
@@ -194,257 +134,62 @@
   // Perform the operations corresponding to the ready file descriptors
   // contained in the given descriptor set.
   template <typename Descriptor_Set>
- void perform_operations_for_descriptors(const Descriptor_Set& descriptors,
- const boost::system::error_code& result)
+ void perform_operations_for_descriptors(
+ const Descriptor_Set& descriptors, op_queue<operation>& ops)
   {
- typename operation_map::iterator i = operations_.begin();
+ typename operations_map::iterator i = operations_.begin();
     while (i != operations_.end())
     {
- typename operation_map::iterator op_iter = i++;
+ typename operations_map::iterator op_iter = i++;
       if (descriptors.is_set(op_iter->first))
       {
- op_base* this_op = op_iter->second;
- op_iter->second = this_op->next_;
- this_op->next_ = complete_operations_;
- complete_operations_ = this_op;
- bool done = this_op->perform(result);
- if (done)
- {
- if (!op_iter->second)
- operations_.erase(op_iter);
- }
- else
+ while (reactor_op* op = op_iter->second.op_queue_.front())
         {
- // Operation has not finished yet, so leave at front of queue, and
- // remove from the completed list.
- complete_operations_ = this_op->next_;
- this_op->next_ = op_iter->second;
- op_iter->second = this_op;
+ if (op->perform())
+ {
+ op_iter->second.op_queue_.pop();
+ ops.push(op);
+ }
+ else
+ {
+ break;
+ }
         }
- }
- }
- }
 
- // 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_ = complete_operations_;
- complete_operations_ = this_op;
- this_op->perform(boost::asio::error::operation_aborted);
- }
- }
-
- // Complete all operations that are waiting to be completed.
- void complete_operations()
- {
- while (complete_operations_)
- {
- op_base* next_op = complete_operations_->next_;
- complete_operations_->next_ = 0;
- complete_operations_->complete();
- complete_operations_ = next_op;
+ if (op_iter->second.op_queue_.empty())
+ operations_.erase(op_iter);
+ }
     }
   }
 
- // Destroy all operations owned by the queue.
- void destroy_operations()
+ // Get all operations owned by the queue.
+ void get_all_operations(op_queue<operation>& ops)
   {
- while (cancelled_operations_)
- {
- op_base* next_op = cancelled_operations_->next_;
- cancelled_operations_->next_ = 0;
- cancelled_operations_->destroy();
- cancelled_operations_ = next_op;
- }
-
- while (complete_operations_)
- {
- 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();
+ typename operations_map::iterator i = operations_.begin();
     while (i != operations_.end())
     {
- typename operation_map::iterator op_iter = i++;
- op_base* curr_op = op_iter->second;
+ typename operations_map::iterator op_iter = i++;
+ ops.push(op_iter->second.op_queue_);
       operations_.erase(op_iter);
- while (curr_op)
- {
- op_base* next_op = curr_op->next_;
- curr_op->next_ = 0;
- curr_op->destroy();
- curr_op = next_op;
- }
     }
   }
 
 private:
- // Base class for reactor operations. A function pointer is used instead of
- // virtual functions to avoid the associated overhead.
- class op_base
+ struct operations
   {
- public:
- // Get the descriptor associated with the operation.
- Descriptor descriptor() const
- {
- return descriptor_;
- }
-
- // Perform the operation.
- 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()
- {
- complete_func_(this, result_, bytes_transferred_);
- }
-
- // Destroy the operation.
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- 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(perform_func_type perform_func, complete_func_type complete_func,
- destroy_func_type destroy_func, Descriptor descriptor)
- : perform_func_(perform_func),
- complete_func_(complete_func),
- destroy_func_(destroy_func),
- descriptor_(descriptor),
- result_(),
- bytes_transferred_(0),
- next_(0)
- {
- }
-
- // Prevent deletion through this type.
- ~op_base()
- {
- }
-
- private:
- friend class reactor_op_queue<Descriptor>;
-
- // 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 operation.
- destroy_func_type destroy_func_;
+ operations() {}
+ operations(const operations&) {}
+ void operator=(const operations&) {}
 
- // 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 operations.
- template <typename Operation>
- class op
- : public op_base
- {
- public:
- // Constructor.
- op(Descriptor descriptor, Operation operation)
- : op_base(&op<Operation>::do_perform, &op<Operation>::do_complete,
- &op<Operation>::do_destroy, descriptor),
- operation_(operation)
- {
- }
-
- // 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)
- {
- // 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);
- }
-
- // Destroy the operation.
- static void do_destroy(op_base* 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);
-
- // A sub-object of the operation may be the true owner of the memory
- // associated with the operation. Consequently, a local copy of the
- // operation is required to ensure that any owning sub-object remains
- // valid until after we have deallocated the memory here.
- Operation operation(this_op->operation_);
- (void)operation;
-
- // Free the memory associated with the operation.
- ptr.reset();
- }
-
- private:
- Operation operation_;
+ // The operations waiting on the desccriptor.
+ op_queue<reactor_op> op_queue_;
   };
 
   // The type for a map of operations.
- typedef hash_map<Descriptor, op_base*> operation_map;
+ typedef hash_map<Descriptor, operations> operations_map;
 
   // The operations that are currently executing asynchronously.
- operation_map operations_;
-
- // The list of operations that have been cancelled.
- op_base* cancelled_operations_;
-
- // The list of operations waiting to be completed.
- op_base* complete_operations_;
+ operations_map operations_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/resolver_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/resolver_service.hpp (original)
+++ branches/release/boost/asio/detail/resolver_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -27,8 +27,10 @@
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/mutex.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/operation.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
@@ -89,7 +91,10 @@
     : boost::asio::detail::service_base<
         resolver_service<Protocol> >(io_service),
       mutex_(),
+ io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)),
       work_io_service_(new boost::asio::io_service),
+ work_io_service_impl_(boost::asio::use_service<
+ io_service_impl>(*work_io_service_)),
       work_(new boost::asio::io_service::work(*work_io_service_)),
       work_thread_(0)
   {
@@ -143,7 +148,7 @@
     std::string service_name = query.service_name();
     boost::asio::detail::addrinfo_type hints = query.hints();
 
- socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0,
+ socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
         service_name.c_str(), &hints, &address_info, ec);
     auto_addrinfo auto_address_info(address_info);
 
@@ -154,54 +159,84 @@
   }
 
   template <typename Handler>
- class resolve_query_handler
+ class resolve_op
+ : public operation
   {
   public:
- resolve_query_handler(implementation_type impl, const query_type& query,
- boost::asio::io_service& io_service, Handler handler)
- : impl_(impl),
+ resolve_op(implementation_type impl, const query_type& query,
+ io_service_impl& io_service_impl, Handler handler)
+ : operation(&resolve_op::do_complete),
+ impl_(impl),
         query_(query),
- io_service_(io_service),
- work_(io_service),
+ io_service_impl_(io_service_impl),
         handler_(handler)
     {
     }
 
- void operator()()
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
     {
- // Check if the operation has been cancelled.
- if (impl_.expired())
+ // Take ownership of the operation object.
+ resolve_op* o(static_cast<resolve_op*>(base));
+ typedef handler_alloc_traits<Handler, resolve_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ if (owner)
       {
- iterator_type iterator;
- io_service_.post(boost::asio::detail::bind_handler(handler_,
- boost::asio::error::operation_aborted, iterator));
- return;
+ if (owner != &o->io_service_impl_)
+ {
+ // The operation is being run on the worker io_service. Time to
+ // perform the resolver operation.
+
+ if (o->impl_.expired())
+ {
+ // THe operation has been cancelled.
+ o->ec_ = boost::asio::error::operation_aborted;
+ }
+ else
+ {
+ // Perform the blocking host resolution operation.
+ boost::asio::detail::addrinfo_type* address_info = 0;
+ std::string host_name = o->query_.host_name();
+ std::string service_name = o->query_.service_name();
+ boost::asio::detail::addrinfo_type hints = o->query_.hints();
+ socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
+ service_name.c_str(), &hints, &address_info, o->ec_);
+ auto_addrinfo auto_address_info(address_info);
+ o->iter_ = iterator_type::create(
+ address_info, host_name, service_name);
+ }
+
+ o->io_service_impl_.post_deferred_completion(o);
+ ptr.release();
+ }
+ else
+ {
+ // The operation has been returned to the main io_serice. The
+ // completion handler is ready to be delivered.
+
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object
+ // remains valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, iterator_type>
+ handler(o->handler_, o->ec_, o->iter_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
       }
-
- // Perform the blocking host resolution operation.
- boost::asio::detail::addrinfo_type* address_info = 0;
- std::string host_name = query_.host_name();
- std::string service_name = query_.service_name();
- boost::asio::detail::addrinfo_type hints = query_.hints();
- boost::system::error_code ec;
- socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0,
- service_name.c_str(), &hints, &address_info, ec);
- auto_addrinfo auto_address_info(address_info);
-
- // Invoke the handler and pass the result.
- iterator_type iterator;
- if (!ec)
- iterator = iterator_type::create(address_info, host_name, service_name);
- io_service_.post(boost::asio::detail::bind_handler(
- handler_, ec, iterator));
     }
 
   private:
     boost::weak_ptr<void> impl_;
     query_type query_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
+ io_service_impl& io_service_impl_;
     Handler handler_;
+ boost::system::error_code ec_;
+ iterator_type iter_;
   };
 
   // Asynchronously resolve a query to a list of entries.
@@ -209,12 +244,19 @@
   void async_resolve(implementation_type& impl, const query_type& query,
       Handler handler)
   {
+ // Allocate and construct an operation to wrap the handler.
+ typedef resolve_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ impl, query, io_service_impl_, handler);
+
     if (work_io_service_)
     {
       start_work_thread();
- work_io_service_->post(
- resolve_query_handler<Handler>(
- impl, query, this->get_io_service(), handler));
+ io_service_impl_.work_started();
+ work_io_service_impl_.post_immediate_completion(ptr.get());
+ ptr.release();
     }
   }
 
@@ -243,61 +285,89 @@
   }
 
   template <typename Handler>
- class resolve_endpoint_handler
+ class resolve_endpoint_op
+ : public operation
   {
   public:
- resolve_endpoint_handler(implementation_type impl,
- const endpoint_type& endpoint, boost::asio::io_service& io_service,
- Handler handler)
- : impl_(impl),
- endpoint_(endpoint),
- io_service_(io_service),
- work_(io_service),
+ resolve_endpoint_op(implementation_type impl, const endpoint_type& ep,
+ io_service_impl& io_service_impl, Handler handler)
+ : operation(&resolve_endpoint_op::do_complete),
+ impl_(impl),
+ ep_(ep),
+ io_service_impl_(io_service_impl),
         handler_(handler)
     {
     }
 
- void operator()()
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
     {
- // Check if the operation has been cancelled.
- if (impl_.expired())
- {
- iterator_type iterator;
- io_service_.post(boost::asio::detail::bind_handler(handler_,
- boost::asio::error::operation_aborted, iterator));
- return;
- }
-
+ // Take ownership of the operation object.
+ resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
+ typedef handler_alloc_traits<Handler, resolve_endpoint_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
- // First try resolving with the service name. If that fails try resolving
- // but allow the service to be returned as a number.
- char host_name[NI_MAXHOST];
- char service_name[NI_MAXSERV];
- int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
- boost::system::error_code ec;
- socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
- host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
- if (ec)
+ if (owner)
       {
- flags |= NI_NUMERICSERV;
- socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
- host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+ if (owner != &o->io_service_impl_)
+ {
+ // The operation is being run on the worker io_service. Time to
+ // perform the resolver operation.
+
+ if (o->impl_.expired())
+ {
+ // THe operation has been cancelled.
+ o->ec_ = boost::asio::error::operation_aborted;
+ }
+ else
+ {
+ // Perform the blocking endoint resolution operation.
+ char host_name[NI_MAXHOST];
+ char service_name[NI_MAXSERV];
+ int flags = o->ep_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
+ socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
+ host_name, NI_MAXHOST, service_name,
+ NI_MAXSERV, flags, o->ec_);
+ if (o->ec_)
+ {
+ flags |= NI_NUMERICSERV;
+ socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
+ host_name, NI_MAXHOST, service_name,
+ NI_MAXSERV, flags, o->ec_);
+ }
+ o->iter_ = iterator_type::create(o->ep_, host_name, service_name);
+ }
+
+ o->io_service_impl_.post_deferred_completion(o);
+ ptr.release();
+ }
+ else
+ {
+ // The operation has been returned to the main io_serice. The
+ // completion handler is ready to be delivered.
+
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object
+ // remains valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, iterator_type>
+ handler(o->handler_, o->ec_, o->iter_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
       }
-
- // Invoke the handler and pass the result.
- iterator_type iterator;
- if (!ec)
- iterator = iterator_type::create(endpoint_, host_name, service_name);
- io_service_.post(boost::asio::detail::bind_handler(
- handler_, ec, iterator));
     }
 
   private:
     boost::weak_ptr<void> impl_;
- endpoint_type endpoint_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
+ endpoint_type ep_;
+ io_service_impl& io_service_impl_;
     Handler handler_;
+ boost::system::error_code ec_;
+ iterator_type iter_;
   };
 
   // Asynchronously resolve an endpoint to a list of entries.
@@ -305,12 +375,19 @@
   void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
       Handler handler)
   {
+ // Allocate and construct an operation to wrap the handler.
+ typedef resolve_endpoint_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ impl, endpoint, io_service_impl_, handler);
+
     if (work_io_service_)
     {
       start_work_thread();
- work_io_service_->post(
- resolve_endpoint_handler<Handler>(
- impl, endpoint, this->get_io_service(), handler));
+ io_service_impl_.work_started();
+ work_io_service_impl_.post_immediate_completion(ptr.get());
+ ptr.release();
     }
   }
 
@@ -340,9 +417,15 @@
   // Mutex to protect access to internal data.
   boost::asio::detail::mutex mutex_;
 
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_impl_;
+
   // Private io_service used for performing asynchronous host resolution.
   boost::scoped_ptr<boost::asio::io_service> work_io_service_;
 
+ // The work io_service implementation used to post completions.
+ io_service_impl& work_io_service_impl_;
+
   // Work for the private io_service to perform.
   boost::scoped_ptr<boost::asio::io_service::work> work_;
 

Modified: branches/release/boost/asio/detail/select_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/select_reactor.hpp (original)
+++ branches/release/boost/asio/detail/select_reactor.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -22,9 +22,6 @@
 #include <boost/asio/detail/push_options.hpp>
 #include <cstddef>
 #include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/shared_ptr.hpp>
-#include <vector>
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/io_service.hpp>
@@ -32,6 +29,8 @@
 #include <boost/asio/detail/fd_set_adapter.hpp>
 #include <boost/asio/detail/mutex.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/select_reactor_fwd.hpp>
@@ -39,9 +38,11 @@
 #include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/task_io_service.hpp>
 #include <boost/asio/detail/thread.hpp>
-#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/timer_queue_fwd.hpp>
+#include <boost/asio/detail/timer_queue_set.hpp>
 
 namespace boost {
 namespace asio {
@@ -52,6 +53,14 @@
   : public boost::asio::detail::service_base<select_reactor<Own_Thread> >
 {
 public:
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ enum { read_op = 0, write_op = 1, except_op = 2,
+ max_select_ops = 3, connect_op = 3, max_ops = 4 };
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ enum { read_op = 0, write_op = 1, except_op = 2,
+ max_select_ops = 3, connect_op = 1, max_ops = 3 };
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
   // Per-descriptor data.
   struct per_descriptor_data
   {
@@ -61,13 +70,9 @@
   select_reactor(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         select_reactor<Own_Thread> >(io_service),
+ io_service_(use_service<io_service_impl>(io_service)),
       mutex_(),
- select_in_progress_(false),
       interrupter_(),
- read_op_queue_(),
- write_op_queue_(),
- except_op_queue_(),
- pending_cancellations_(),
       stop_thread_(false),
       thread_(0),
       shutdown_(false)
@@ -94,31 +99,29 @@
     stop_thread_ = true;
     lock.unlock();
 
- if (thread_)
+ if (Own_Thread)
     {
- interrupter_.interrupt();
- thread_->join();
- delete thread_;
- thread_ = 0;
+ if (thread_)
+ {
+ interrupter_.interrupt();
+ thread_->join();
+ delete thread_;
+ thread_ = 0;
+ }
     }
 
- read_op_queue_.destroy_operations();
- write_op_queue_.destroy_operations();
- except_op_queue_.destroy_operations();
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- timer_queues_[i]->destroy_timers();
- timer_queues_.clear();
+ op_queue<operation> ops;
+
+ for (int i = 0; i < max_ops; ++i)
+ op_queue_[i].get_all_operations(ops);
+
+ timer_queues_.get_all_timers(ops);
   }
 
   // Initialise the task, but only if the reactor is not in its own thread.
   void init_task()
   {
- if (!Own_Thread)
- {
- typedef task_io_service<select_reactor<Own_Thread> > task_io_service_type;
- use_service<task_io_service_type>(this->get_io_service()).init_task();
- }
+ io_service_.init_task();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -128,111 +131,17 @@
     return 0;
   }
 
- // Start a new read operation. The handler object will be invoked when the
- // given descriptor is ready to be read, or an error has occurred.
- template <typename Handler>
- void start_read_op(socket_type descriptor, per_descriptor_data&,
- Handler handler, bool /*allow_speculative_read*/ = true)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
- if (read_op_queue_.enqueue_operation(descriptor, handler))
- interrupter_.interrupt();
- }
-
- // Start a new write operation. The handler object will be invoked when the
- // given descriptor is ready to be written, or an error has occurred.
- template <typename Handler>
- void start_write_op(socket_type descriptor, per_descriptor_data&,
- Handler handler, bool /*allow_speculative_write*/ = true)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
- if (write_op_queue_.enqueue_operation(descriptor, handler))
- interrupter_.interrupt();
- }
-
- // Start a new exception operation. The handler object will be invoked when
- // the given descriptor has exception information, or an error has occurred.
- template <typename Handler>
- void start_except_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
- {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
- if (except_op_queue_.enqueue_operation(descriptor, handler))
- interrupter_.interrupt();
- }
-
- // Wrapper for connect handlers to enable the handler object to be placed
- // in both the write and the except operation queues, but ensure that only
- // one of the handlers is called.
- template <typename Handler>
- class connect_handler_wrapper
- {
- public:
- connect_handler_wrapper(socket_type descriptor,
- boost::shared_ptr<bool> completed,
- select_reactor<Own_Thread>& reactor, Handler handler)
- : descriptor_(descriptor),
- completed_(completed),
- reactor_(reactor),
- handler_(handler)
- {
- }
-
- 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_.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:
- socket_type descriptor_;
- boost::shared_ptr<bool> completed_;
- select_reactor<Own_Thread>& reactor_;
- Handler handler_;
- };
-
- // Start new write and exception operations. The handler object will be
- // invoked when the given descriptor is ready for writing or has exception
- // information available, or an error has occurred. The handler will be called
- // only once.
- template <typename Handler>
- void start_connect_op(socket_type descriptor,
- per_descriptor_data&, Handler handler)
+ // Start a new operation. The reactor operation will be performed when the
+ // given descriptor is flagged as ready, or an error has occurred.
+ void start_op(int op_type, socket_type descriptor,
+ per_descriptor_data&, reactor_op* op, bool)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
     {
- boost::shared_ptr<bool> completed(new bool(false));
- connect_handler_wrapper<Handler> wrapped_handler(
- descriptor, completed, *this, handler);
- bool interrupt = write_op_queue_.enqueue_operation(
- descriptor, wrapped_handler);
- interrupt = except_op_queue_.enqueue_operation(
- descriptor, wrapped_handler) || interrupt;
- if (interrupt)
+ bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+ io_service_.work_started();
+ if (first)
         interrupter_.interrupt();
     }
   }
@@ -243,17 +152,7 @@
   void cancel_ops(socket_type descriptor, per_descriptor_data&)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- cancel_ops_unlocked(descriptor);
- }
-
- // Enqueue cancellation of all operations associated with the given
- // descriptor. The handlers associated with the descriptor will be invoked
- // with the operation_aborted error. This function does not acquire the
- // select_reactor's mutex, and so should only be used when the reactor lock is
- // already held.
- void enqueue_cancel_ops_unlocked(socket_type descriptor)
- {
- pending_cancellations_.push_back(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Cancel any operations that are running against the descriptor and remove
@@ -261,7 +160,7 @@
   void close_descriptor(socket_type descriptor, per_descriptor_data&)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- cancel_ops_unlocked(descriptor);
+ cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
   }
 
   // Add a new timer queue to the reactor.
@@ -269,7 +168,7 @@
   void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- timer_queues_.push_back(&timer_queue);
+ timer_queues_.insert(&timer_queue);
   }
 
   // Remove a timer queue from the reactor.
@@ -277,252 +176,186 @@
   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- if (timer_queues_[i] == &timer_queue)
- {
- timer_queues_.erase(timer_queues_.begin() + i);
- return;
- }
- }
+ timer_queues_.erase(&timer_queue);
   }
 
- // Schedule a timer in the given timer queue to expire at the specified
- // absolute time. The handler object will be invoked when the timer expires.
- template <typename Time_Traits, typename Handler>
+ // 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, Handler handler, void* token)
+ const typename Time_Traits::time_type& time, timer_op* op, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
- if (timer_queue.enqueue_timer(time, handler, token))
+ {
+ bool earliest = timer_queue.enqueue_timer(time, op, token);
+ io_service_.work_started();
+ if (earliest)
         interrupter_.interrupt();
+ }
   }
 
- // Cancel the timer associated with the given token. Returns the number of
- // handlers that have been posted or dispatched.
+ // 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)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- std::size_t n = timer_queue.cancel_timer(token);
- if (n > 0)
- interrupter_.interrupt();
+ op_queue<operation> ops;
+ std::size_t n = timer_queue.cancel_timer(token, ops);
+ lock.unlock();
+ io_service_.post_deferred_completions(ops);
     return n;
   }
 
-private:
- friend class task_io_service<select_reactor<Own_Thread> >;
-
   // Run select once until interrupted or events are ready to be dispatched.
- void run(bool block)
+ void run(bool block, op_queue<operation>& ops)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- // Dispatch any operation cancellations that were made while the select
- // loop was not running.
- 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_)
- {
- complete_operations_and_timers(lock);
- return;
- }
+ if (Own_Thread)
+ if (stop_thread_)
+ return;
+
+ // Set up the descriptor sets.
+ fd_set_adapter fds[max_select_ops];
+ fds[read_op].set(interrupter_.read_descriptor());
+ socket_type max_fd = 0;
+ bool have_work_to_do = !timer_queues_.all_empty();
+ for (int i = 0; i < max_select_ops; ++i)
+ {
+ have_work_to_do = have_work_to_do || !op_queue_[i].empty();
+ op_queue_[i].get_descriptors(fds[i], ops);
+ if (fds[i].max_descriptor() > max_fd)
+ max_fd = fds[i].max_descriptor();
+ }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Connection operations on Windows use both except and write fd_sets.
+ have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
+ op_queue_[connect_op].get_descriptors(fds[write_op], ops);
+ if (fds[write_op].max_descriptor() > max_fd)
+ max_fd = fds[write_op].max_descriptor();
+ op_queue_[connect_op].get_descriptors(fds[except_op], ops);
+ if (fds[except_op].max_descriptor() > max_fd)
+ max_fd = fds[except_op].max_descriptor();
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
- if (!block && read_op_queue_.empty() && write_op_queue_.empty()
- && except_op_queue_.empty() && all_timer_queues_are_empty())
- {
- complete_operations_and_timers(lock);
+ if (!block && !have_work_to_do)
       return;
- }
 
- // Set up the descriptor sets.
- fd_set_adapter read_fds;
- read_fds.set(interrupter_.read_descriptor());
- read_op_queue_.get_descriptors(read_fds);
- fd_set_adapter write_fds;
- write_op_queue_.get_descriptors(write_fds);
- fd_set_adapter except_fds;
- except_op_queue_.get_descriptors(except_fds);
- socket_type max_fd = read_fds.max_descriptor();
- if (write_fds.max_descriptor() > max_fd)
- max_fd = write_fds.max_descriptor();
- if (except_fds.max_descriptor() > max_fd)
- max_fd = except_fds.max_descriptor();
-
- // Block on the select call without holding the lock so that new
- // operations can be started while the call is executing.
+ // Determine how long to block while waiting for events.
     timeval tv_buf = { 0, 0 };
     timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
- select_in_progress_ = true;
+
     lock.unlock();
+
+ // Block on the select call until descriptors become ready.
     boost::system::error_code ec;
     int retval = socket_ops::select(static_cast<int>(max_fd + 1),
- read_fds, write_fds, except_fds, tv, ec);
- lock.lock();
- select_in_progress_ = false;
+ fds[read_op], fds[write_op], fds[except_op], tv, ec);
 
     // Reset the interrupter.
- if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor()))
+ if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
       interrupter_.reset();
 
+ lock.lock();
+
     // Dispatch all ready operations.
     if (retval > 0)
     {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Connection operations on Windows use both except and write fd_sets.
+ op_queue_[connect_op].perform_operations_for_descriptors(
+ fds[except_op], ops);
+ op_queue_[connect_op].perform_operations_for_descriptors(
+ fds[write_op], ops);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
       // Exception operations must be processed first to ensure that any
       // out-of-band data is read before normal data.
- 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)
- {
- timer_queues_[i]->dispatch_timers();
- timer_queues_[i]->dispatch_cancellations();
+ for (int i = max_select_ops - 1; i >= 0; --i)
+ op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
     }
+ timer_queues_.get_ready_timers(ops);
+ }
 
- // Issue any pending cancellations.
- for (size_t i = 0; i < pending_cancellations_.size(); ++i)
- cancel_ops_unlocked(pending_cancellations_[i]);
- pending_cancellations_.clear();
-
- complete_operations_and_timers(lock);
+ // Interrupt the select loop.
+ void interrupt()
+ {
+ interrupter_.interrupt();
   }
 
+private:
   // Run the select loop in the thread.
   void run_thread()
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
- while (!stop_thread_)
+ if (Own_Thread)
     {
- lock.unlock();
- run(true);
- lock.lock();
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ while (!stop_thread_)
+ {
+ lock.unlock();
+ op_queue<operation> ops;
+ run(true, ops);
+ io_service_.post_deferred_completions(ops);
+ lock.lock();
+ }
     }
   }
 
   // Entry point for the select loop thread.
   static void call_run_thread(select_reactor* reactor)
   {
- reactor->run_thread();
- }
-
- // Interrupt the select loop.
- void interrupt()
- {
- interrupter_.interrupt();
- }
-
- // Check if all timer queues are empty.
- bool all_timer_queues_are_empty() const
- {
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- if (!timer_queues_[i]->empty())
- return false;
- return true;
+ if (Own_Thread)
+ {
+ reactor->run_thread();
+ }
   }
 
   // Get the timeout value for the select call.
   timeval* get_timeout(timeval& tv)
   {
- if (all_timer_queues_are_empty())
- return 0;
-
     // By default we will wait no longer than 5 minutes. This will ensure that
     // any changes to the system clock are detected after no longer than this.
- boost::posix_time::time_duration minimum_wait_duration
- = boost::posix_time::minutes(5);
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- boost::posix_time::time_duration wait_duration
- = timer_queues_[i]->wait_duration();
- if (wait_duration < minimum_wait_duration)
- minimum_wait_duration = wait_duration;
- }
-
- if (minimum_wait_duration > boost::posix_time::time_duration())
- {
- tv.tv_sec = minimum_wait_duration.total_seconds();
- tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000;
- }
- else
- {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- }
-
+ long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+ tv.tv_sec = usec / 1000000;
+ tv.tv_usec = usec % 1000000;
     return &tv;
   }
 
- // Cancel all operations associated with the given descriptor. The do_cancel
- // function of the handler objects will be invoked. This function does not
- // acquire the select_reactor's mutex.
- void cancel_ops_unlocked(socket_type descriptor)
- {
- bool interrupt = read_op_queue_.cancel_operations(descriptor);
- interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
- interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
- if (interrupt)
+ // Cancel all operations associated with the given descriptor. This function
+ // does not acquire the select_reactor's mutex.
+ void cancel_ops_unlocked(socket_type descriptor,
+ const boost::system::error_code& ec)
+ {
+ bool need_interrupt = false;
+ op_queue<operation> ops;
+ for (int i = 0; i < max_ops; ++i)
+ need_interrupt = op_queue_[i].cancel_operations(
+ descriptor, ops, ec) || need_interrupt;
+ io_service_.post_deferred_completions(ops);
+ if (need_interrupt)
       interrupter_.interrupt();
   }
 
- // Clean up operations and timers. We must not hold the lock since the
- // 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 complete_operations_and_timers(
- boost::asio::detail::mutex::scoped_lock& lock)
- {
- timer_queues_for_cleanup_ = timer_queues_;
- lock.unlock();
- 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]->complete_timers();
- }
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_;
 
   // Mutex to protect access to internal data.
   boost::asio::detail::mutex mutex_;
 
- // Whether the select loop is currently running or not.
- bool select_in_progress_;
-
   // The interrupter is used to break a blocking select call.
   select_interrupter interrupter_;
 
- // The queue of read operations.
- reactor_op_queue<socket_type> read_op_queue_;
-
- // The queue of write operations.
- reactor_op_queue<socket_type> write_op_queue_;
-
- // The queue of exception operations.
- reactor_op_queue<socket_type> except_op_queue_;
+ // The queues of read, write and except operations.
+ reactor_op_queue<socket_type> op_queue_[max_ops];
 
   // The timer queues.
- std::vector<timer_queue_base*> timer_queues_;
-
- // A copy of the timer queues, used when cleaning up timers. The copy is
- // stored as a class data member to avoid unnecessary memory allocation.
- std::vector<timer_queue_base*> timer_queues_for_cleanup_;
-
- // The descriptors that are pending cancellation.
- std::vector<socket_type> pending_cancellations_;
+ timer_queue_set timer_queues_;
 
   // Does the reactor loop thread need to stop.
   bool stop_thread_;

Modified: branches/release/boost/asio/detail/service_registry.hpp
==============================================================================
--- branches/release/boost/asio/detail/service_registry.hpp (original)
+++ branches/release/boost/asio/detail/service_registry.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -18,7 +18,6 @@
 #include <boost/asio/detail/push_options.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
-#include <memory>
 #include <typeinfo>
 #include <boost/asio/detail/pop_options.hpp>
 
@@ -80,7 +79,7 @@
     while (first_service_)
     {
       boost::asio::io_service::service* next_service = first_service_->next_;
- delete first_service_;
+ destroy(first_service_);
       first_service_ = next_service;
     }
   }
@@ -91,14 +90,105 @@
   template <typename Service>
   Service& use_service()
   {
+ boost::asio::io_service::service::key key;
+ init_key(key, Service::id);
+ factory_type factory = &service_registry::create<Service>;
+ return *static_cast<Service*>(do_use_service(key, factory));
+ }
+
+ // Add a service object. Returns false on error, in which case ownership of
+ // the object is retained by the caller.
+ template <typename Service>
+ bool add_service(Service* new_service)
+ {
+ boost::asio::io_service::service::key key;
+ init_key(key, Service::id);
+ return do_add_service(key, new_service);
+ }
+
+ // Check whether a service object of the specified type already exists.
+ template <typename Service>
+ bool has_service() const
+ {
+ boost::asio::io_service::service::key key;
+ init_key(key, Service::id);
+ return do_has_service(key);
+ }
+
+private:
+ // Initialise a service's key based on its id.
+ void init_key(boost::asio::io_service::service::key& key,
+ const boost::asio::io_service::id& id)
+ {
+ key.type_info_ = 0;
+ key.id_ = &id;
+ }
+
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ // Initialise a service's key based on its id.
+ template <typename Service>
+ void init_key(boost::asio::io_service::service::key& key,
+ const boost::asio::detail::service_id<Service>& /*id*/)
+ {
+ key.type_info_ = &typeid(typeid_wrapper<Service>);
+ key.id_ = 0;
+ }
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
+ // Check if a service matches the given id.
+ static bool keys_match(
+ const boost::asio::io_service::service::key& key1,
+ const boost::asio::io_service::service::key& key2)
+ {
+ if (key1.id_ && key2.id_)
+ if (key1.id_ == key2.id_)
+ return true;
+ if (key1.type_info_ && key2.type_info_)
+ if (*key1.type_info_ == *key2.type_info_)
+ return true;
+ return false;
+ }
+
+ // The type of a factory function used for creating a service instance.
+ typedef boost::asio::io_service::service*
+ (*factory_type)(boost::asio::io_service&);
+
+ // Factory function for creating a service instance.
+ template <typename Service>
+ static boost::asio::io_service::service* create(
+ boost::asio::io_service& owner)
+ {
+ return new Service(owner);
+ }
+
+ // Destroy a service instance.
+ static void destroy(boost::asio::io_service::service* service)
+ {
+ delete service;
+ }
+
+ // Helper class to manage service pointers.
+ struct auto_service_ptr
+ {
+ boost::asio::io_service::service* ptr_;
+ ~auto_service_ptr() { destroy(ptr_); }
+ };
+
+ // Get the service object corresponding to the specified service key. Will
+ // create a new service object automatically if no such object already
+ // exists. Ownership of the service object is not transferred to the caller.
+ boost::asio::io_service::service* do_use_service(
+ const boost::asio::io_service::service::key& key,
+ factory_type factory)
+ {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- // First see if there is an existing service object for the given type.
+ // First see if there is an existing service object with the given key.
     boost::asio::io_service::service* service = first_service_;
     while (service)
     {
- if (service_id_matches(*service, Service::id))
- return *static_cast<Service*>(service);
+ if (keys_match(service->key_, key))
+ return service;
       service = service->next_;
     }
 
@@ -106,9 +196,8 @@
     // at this time to allow for nested calls into this function from the new
     // service's constructor.
     lock.unlock();
- std::auto_ptr<Service> new_service(new Service(owner_));
- init_service_id(*new_service, Service::id);
- Service& new_service_ref = *new_service;
+ auto_service_ptr new_service = { factory(owner_) };
+ new_service.ptr_->key_ = key;
     lock.lock();
 
     // Check that nobody else created another service object of the same type
@@ -116,52 +205,52 @@
     service = first_service_;
     while (service)
     {
- if (service_id_matches(*service, Service::id))
- return *static_cast<Service*>(service);
+ if (keys_match(service->key_, key))
+ return service;
       service = service->next_;
     }
 
     // Service was successfully initialised, pass ownership to registry.
- new_service->next_ = first_service_;
- first_service_ = new_service.release();
-
- return new_service_ref;
+ new_service.ptr_->next_ = first_service_;
+ first_service_ = new_service.ptr_;
+ new_service.ptr_ = 0;
+ return first_service_;
   }
 
   // Add a service object. Returns false on error, in which case ownership of
   // the object is retained by the caller.
- template <typename Service>
- bool add_service(Service* new_service)
+ bool do_add_service(
+ const boost::asio::io_service::service::key& key,
+ boost::asio::io_service::service* new_service)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- // Check if there is an existing service object for the given type.
+ // Check if there is an existing service object with the given key.
     boost::asio::io_service::service* service = first_service_;
     while (service)
     {
- if (service_id_matches(*service, Service::id))
+ if (keys_match(service->key_, key))
         return false;
       service = service->next_;
     }
 
     // Take ownership of the service object.
- init_service_id(*new_service, Service::id);
+ new_service->key_ = key;
     new_service->next_ = first_service_;
     first_service_ = new_service;
 
     return true;
   }
 
- // Check whether a service object of the specified type already exists.
- template <typename Service>
- bool has_service() const
+ // Check whether a service object with the specified key already exists.
+ bool do_has_service(const boost::asio::io_service::service::key& key) const
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
     boost::asio::io_service::service* service = first_service_;
     while (service)
     {
- if (service_id_matches(*service, Service::id))
+ if (keys_match(service->key_, key))
         return true;
       service = service->next_;
     }
@@ -169,46 +258,6 @@
     return false;
   }
 
-private:
- // Set a service's id.
- void init_service_id(boost::asio::io_service::service& service,
- const boost::asio::io_service::id& id)
- {
- service.type_info_ = 0;
- service.id_ = &id;
- }
-
-#if !defined(BOOST_ASIO_NO_TYPEID)
- // Set a service's id.
- template <typename Service>
- void init_service_id(boost::asio::io_service::service& service,
- const boost::asio::detail::service_id<Service>& /*id*/)
- {
- service.type_info_ = &typeid(typeid_wrapper<Service>);
- service.id_ = 0;
- }
-#endif // !defined(BOOST_ASIO_NO_TYPEID)
-
- // Check if a service matches the given id.
- static bool service_id_matches(
- const boost::asio::io_service::service& service,
- const boost::asio::io_service::id& id)
- {
- return service.id_ == &id;
- }
-
-#if !defined(BOOST_ASIO_NO_TYPEID)
- // Check if a service matches the given id.
- template <typename Service>
- static bool service_id_matches(
- const boost::asio::io_service::service& service,
- const boost::asio::detail::service_id<Service>& /*id*/)
- {
- return service.type_info_ != 0
- && *service.type_info_ == typeid(typeid_wrapper<Service>);
- }
-#endif // !defined(BOOST_ASIO_NO_TYPEID)
-
   // Mutex to protect access to internal data.
   mutable boost::asio::detail::mutex mutex_;
 

Modified: branches/release/boost/asio/detail/strand_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/strand_service.hpp (original)
+++ branches/release/boost/asio/detail/strand_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -18,19 +18,19 @@
 #include <boost/asio/detail/push_options.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
-#include <boost/aligned_storage.hpp>
-#include <boost/assert.hpp>
 #include <boost/functional/hash.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
 #include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/completion_handler.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/operation.hpp>
 #include <boost/asio/detail/service_base.hpp>
 
 namespace boost {
@@ -41,252 +41,45 @@
 class strand_service
   : public boost::asio::detail::service_base<strand_service>
 {
+private:
+ struct on_do_complete_exit;
+ struct on_dispatch_exit;
+
 public:
- class handler_base;
- class invoke_current_handler;
- class post_next_waiter_on_exit;
 
   // The underlying implementation of a strand.
   class strand_impl
+ : public operation
   {
   public:
     strand_impl()
- : current_handler_(0),
- first_waiter_(0),
- last_waiter_(0)
+ : operation(&strand_service::do_complete),
+ count_(0)
     {
     }
 
   private:
     // Only this service will have access to the internal values.
     friend class strand_service;
- friend class post_next_waiter_on_exit;
- friend class invoke_current_handler;
+ friend struct on_do_complete_exit;
+ friend struct on_dispatch_exit;
 
     // Mutex to protect access to internal data.
     boost::asio::detail::mutex mutex_;
 
- // The handler that is ready to execute. If this pointer is non-null then it
- // indicates that a handler holds the lock.
- handler_base* current_handler_;
-
- // The start of the list of waiting handlers for the strand.
- handler_base* first_waiter_;
-
- // The end of the list of waiting handlers for the strand.
- handler_base* last_waiter_;
-
- // Storage for posted handlers.
- typedef boost::aligned_storage<128> handler_storage_type;
-#if defined(__BORLANDC__)
- boost::aligned_storage<128> handler_storage_;
-#else
- handler_storage_type handler_storage_;
-#endif
- };
-
- friend class strand_impl;
-
- typedef strand_impl* implementation_type;
-
- // Base class for all handler types.
- class handler_base
- {
- public:
- typedef void (*invoke_func_type)(handler_base*,
- strand_service&, implementation_type&);
- typedef void (*destroy_func_type)(handler_base*);
-
- handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func)
- : next_(0),
- invoke_func_(invoke_func),
- destroy_func_(destroy_func)
- {
- }
-
- void invoke(strand_service& service_impl, implementation_type& impl)
- {
- invoke_func_(this, service_impl, impl);
- }
-
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- ~handler_base()
- {
- }
-
- private:
- friend class strand_service;
- friend class strand_impl;
- friend class post_next_waiter_on_exit;
- handler_base* next_;
- invoke_func_type invoke_func_;
- destroy_func_type destroy_func_;
- };
-
- // Helper class to allow handlers to be dispatched.
- class invoke_current_handler
- {
- public:
- invoke_current_handler(strand_service& service_impl,
- const implementation_type& impl)
- : service_impl_(service_impl),
- impl_(impl)
- {
- }
-
- void operator()()
- {
- impl_->current_handler_->invoke(service_impl_, impl_);
- }
-
- friend void* asio_handler_allocate(std::size_t size,
- invoke_current_handler* this_handler)
- {
- return this_handler->do_handler_allocate(size);
- }
-
- friend void asio_handler_deallocate(void*, std::size_t,
- invoke_current_handler*)
- {
- }
-
- void* do_handler_allocate(std::size_t size)
- {
-#if defined(__BORLANDC__)
- BOOST_ASSERT(size <= boost::aligned_storage<128>::size);
-#else
- BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
-#endif
- (void)size;
- return impl_->handler_storage_.address();
- }
-
- // The asio_handler_invoke hook is not defined here since the default one
- // provides the correct behaviour, and including it here breaks MSVC 7.1
- // in some situations.
-
- private:
- strand_service& service_impl_;
- implementation_type impl_;
- };
-
- // Helper class to automatically enqueue next waiter on block exit.
- class post_next_waiter_on_exit
- {
- public:
- post_next_waiter_on_exit(strand_service& service_impl,
- implementation_type& impl)
- : service_impl_(service_impl),
- impl_(impl),
- cancelled_(false)
- {
- }
-
- ~post_next_waiter_on_exit()
- {
- if (!cancelled_)
- {
- boost::asio::detail::mutex::scoped_lock lock(impl_->mutex_);
- impl_->current_handler_ = impl_->first_waiter_;
- if (impl_->current_handler_)
- {
- impl_->first_waiter_ = impl_->first_waiter_->next_;
- if (impl_->first_waiter_ == 0)
- impl_->last_waiter_ = 0;
- lock.unlock();
- service_impl_.get_io_service().post(
- invoke_current_handler(service_impl_, impl_));
- }
- }
- }
-
- void cancel()
- {
- cancelled_ = true;
- }
+ // The count of handlers in the strand, including the upcall (if any).
+ std::size_t count_;
 
- private:
- strand_service& service_impl_;
- implementation_type& impl_;
- bool cancelled_;
+ // The handlers waiting on the strand.
+ op_queue<operation> queue_;
   };
 
- // Class template for a waiter.
- template <typename Handler>
- class handler_wrapper
- : public handler_base
- {
- public:
- handler_wrapper(Handler handler)
- : handler_base(&handler_wrapper<Handler>::do_invoke,
- &handler_wrapper<Handler>::do_destroy),
- handler_(handler)
- {
- }
-
- static void do_invoke(handler_base* base,
- strand_service& service_impl, implementation_type& impl)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- post_next_waiter_on_exit p1(service_impl, impl);
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(h->handler_);
-
- // A handler object must still be valid when the next waiter is posted
- // since destroying the last handler might cause the strand object to be
- // destroyed. Therefore we create a second post_next_waiter_on_exit object
- // that will be destroyed before the handler object.
- p1.cancel();
- post_next_waiter_on_exit p2(service_impl, impl);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Indicate that this strand is executing on the current thread.
- call_stack<strand_impl>::context ctx(impl);
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
-
- static void do_destroy(handler_base* base)
- {
- // Take ownership of the handler object.
- typedef handler_wrapper<Handler> this_type;
- this_type* h(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(h->handler_, h);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(h->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
-
- private:
- Handler handler_;
- };
+ typedef strand_impl* implementation_type;
 
   // Construct a new strand service for the specified io_service.
   explicit strand_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<strand_service>(io_service),
+ io_service_(boost::asio::use_service<io_service_impl>(io_service)),
       mutex_(),
       salt_(0)
   {
@@ -295,37 +88,13 @@
   // Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
- // Construct a list of all handlers to be destroyed.
+ op_queue<operation> ops;
+
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
- handler_base* first_handler = 0;
+
     for (std::size_t i = 0; i < num_implementations; ++i)
- {
       if (strand_impl* impl = implementations_[i].get())
- {
- if (impl->current_handler_)
- {
- impl->current_handler_->next_ = first_handler;
- first_handler = impl->current_handler_;
- impl->current_handler_ = 0;
- }
- if (impl->first_waiter_)
- {
- impl->last_waiter_->next_ = first_handler;
- first_handler = impl->first_waiter_;
- impl->first_waiter_ = 0;
- impl->last_waiter_ = 0;
- }
- }
- }
-
- // Destroy all handlers without holding the lock.
- lock.unlock();
- while (first_handler)
- {
- handler_base* next = first_handler->next_;
- first_handler->destroy();
- first_handler = next;
- }
+ ops.push(impl->queue_);
   }
 
   // Construct a new strand implementation.
@@ -352,45 +121,54 @@
   template <typename Handler>
   void dispatch(implementation_type& impl, Handler handler)
   {
+ // If we are already in the strand then the handler can run immediately.
     if (call_stack<strand_impl>::contains(impl))
     {
+ boost::asio::detail::fenced_block b;
       boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ return;
     }
- else
+
+ // Allocate and construct an object to wrap the handler.
+ typedef completion_handler<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ // If we are running inside the io_service, and no other handler is queued
+ // or running, then the handler can run immediately.
+ bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_);
+ impl->mutex_.lock();
+ bool first = (++impl->count_ == 1);
+ if (can_dispatch && first)
     {
- // Allocate and construct an object to wrap the handler.
- typedef handler_wrapper<Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
- boost::asio::detail::mutex::scoped_lock lock(impl->mutex_);
-
- if (impl->current_handler_ == 0)
- {
- // This handler now has the lock, so can be dispatched immediately.
- impl->current_handler_ = ptr.release();
- lock.unlock();
- this->get_io_service().dispatch(invoke_current_handler(*this, impl));
- }
- else
- {
- // Another handler already holds the lock, so this handler must join
- // the list of waiters. The handler will be posted automatically when
- // its turn comes.
- if (impl->last_waiter_)
- {
- impl->last_waiter_->next_ = ptr.get();
- impl->last_waiter_ = impl->last_waiter_->next_;
- }
- else
- {
- impl->first_waiter_ = ptr.get();
- impl->last_waiter_ = ptr.get();
- }
- ptr.release();
- }
+ // Immediate invocation is allowed.
+ impl->mutex_.unlock();
+
+ // Memory must be releaesed before any upcall is made.
+ ptr.reset();
+
+ // Indicate that this strand is executing on the current thread.
+ call_stack<strand_impl>::context ctx(impl);
+
+ // Ensure the next handler, if any, is scheduled on block exit.
+ on_dispatch_exit on_exit = { &io_service_, impl };
+ (void)on_exit;
+
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ return;
     }
+
+ // Immediate invocation is not allowed, so enqueue for later.
+ impl->queue_.push(ptr.get());
+ impl->mutex_.unlock();
+ ptr.release();
+
+ // The first handler to be enqueued is responsible for scheduling the
+ // strand.
+ if (first)
+ io_service_.post_immediate_completion(impl);
   }
 
   // Request the io_service to invoke the given handler and return immediately.
@@ -398,40 +176,85 @@
   void post(implementation_type& impl, Handler handler)
   {
     // Allocate and construct an object to wrap the handler.
- typedef handler_wrapper<Handler> value_type;
+ typedef completion_handler<Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
     handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- boost::asio::detail::mutex::scoped_lock lock(impl->mutex_);
+ // Add the handler to the queue.
+ impl->mutex_.lock();
+ bool first = (++impl->count_ == 1);
+ impl->queue_.push(ptr.get());
+ impl->mutex_.unlock();
+ ptr.release();
+
+ // The first handler to be enqueue is responsible for scheduling the strand.
+ if (first)
+ io_service_.post_immediate_completion(impl);
+ }
+
+private:
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ if (owner)
+ {
+ strand_impl* impl = static_cast<strand_impl*>(base);
+
+ // Get the next handler to be executed.
+ impl->mutex_.lock();
+ operation* o = impl->queue_.front();
+ impl->queue_.pop();
+ impl->mutex_.unlock();
+
+ // Indicate that this strand is executing on the current thread.
+ call_stack<strand_impl>::context ctx(impl);
+
+ // Ensure the next handler, if any, is scheduled on block exit.
+ on_do_complete_exit on_exit = { owner, impl };
+ (void)on_exit;
+
+ o->complete(*owner);
+ }
+ }
+
+ // Helper class to re-post the strand on exit.
+ struct on_do_complete_exit
+ {
+ io_service_impl* owner_;
+ strand_impl* impl_;
 
- if (impl->current_handler_ == 0)
+ ~on_do_complete_exit()
     {
- // This handler now has the lock, so can be dispatched immediately.
- impl->current_handler_ = ptr.release();
- lock.unlock();
- this->get_io_service().post(invoke_current_handler(*this, impl));
+ impl_->mutex_.lock();
+ bool more_handlers = (--impl_->count_ > 0);
+ impl_->mutex_.unlock();
+
+ if (more_handlers)
+ owner_->post_immediate_completion(impl_);
     }
- else
+ };
+
+ // Helper class to re-post the strand on exit.
+ struct on_dispatch_exit
+ {
+ io_service_impl* io_service_;
+ strand_impl* impl_;
+
+ ~on_dispatch_exit()
     {
- // Another handler already holds the lock, so this handler must join the
- // list of waiters. The handler will be posted automatically when its turn
- // comes.
- if (impl->last_waiter_)
- {
- impl->last_waiter_->next_ = ptr.get();
- impl->last_waiter_ = impl->last_waiter_->next_;
- }
- else
- {
- impl->first_waiter_ = ptr.get();
- impl->last_waiter_ = ptr.get();
- }
- ptr.release();
+ impl_->mutex_.lock();
+ bool more_handlers = (--impl_->count_ > 0);
+ impl_->mutex_.unlock();
+
+ if (more_handlers)
+ io_service_->post_immediate_completion(impl_);
     }
- }
+ };
+
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_;
 
-private:
   // Mutex to protect access to the array of implementations.
   boost::asio::detail::mutex mutex_;
 

Modified: branches/release/boost/asio/detail/task_io_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/task_io_service.hpp (original)
+++ branches/release/boost/asio/detail/task_io_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -15,21 +15,25 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#if defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
-#include <boost/asio/detail/task_io_service_2lock.hpp>
-#else // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
-
 #include <boost/asio/detail/push_options.hpp>
 
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/completion_handler.hpp>
 #include <boost/asio/detail/event.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
-#include <boost/asio/detail/handler_queue.hpp>
 #include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/op_queue.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/task_io_service_fwd.hpp>
+#include <boost/asio/detail/task_io_service_operation.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
 
 namespace boost {
 namespace asio {
@@ -40,6 +44,8 @@
   : public boost::asio::detail::service_base<task_io_service<Task> >
 {
 public:
+ typedef task_io_service_operation<Task> operation;
+
   // Constructor.
   task_io_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
@@ -65,12 +71,12 @@
     lock.unlock();
 
     // Destroy handler objects.
- while (!handler_queue_.empty())
+ while (!op_queue_.empty())
     {
- handler_queue::handler* h = handler_queue_.front();
- handler_queue_.pop();
- if (h != &task_handler_)
- h->destroy();
+ operation* o = op_queue_.front();
+ op_queue_.pop();
+ if (o != &task_operation_)
+ o->destroy();
     }
 
     // Reset to initial state.
@@ -84,14 +90,21 @@
     if (!shutdown_ && !task_)
     {
       task_ = &use_service<Task>(this->get_io_service());
- handler_queue_.push(&task_handler_);
- interrupt_one_idle_thread(lock);
+ op_queue_.push(&task_operation_);
+ wake_one_thread_and_unlock(lock);
     }
   }
 
   // Run the event loop until interrupted or no more work.
   size_t run(boost::system::error_code& ec)
   {
+ ec = boost::system::error_code();
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ return 0;
+ }
+
     typename call_stack<task_io_service>::context ctx(this);
 
     idle_thread_info this_idle_thread;
@@ -100,7 +113,7 @@
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
     size_t n = 0;
- while (do_one(lock, &this_idle_thread, ec))
+ for (; do_one(lock, &this_idle_thread); lock.lock())
       if (n != (std::numeric_limits<size_t>::max)())
         ++n;
     return n;
@@ -109,6 +122,13 @@
   // Run until interrupted or one operation is performed.
   size_t run_one(boost::system::error_code& ec)
   {
+ ec = boost::system::error_code();
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ return 0;
+ }
+
     typename call_stack<task_io_service>::context ctx(this);
 
     idle_thread_info this_idle_thread;
@@ -116,18 +136,25 @@
 
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- return do_one(lock, &this_idle_thread, ec);
+ return do_one(lock, &this_idle_thread);
   }
 
   // Poll for operations without blocking.
   size_t poll(boost::system::error_code& ec)
   {
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
     typename call_stack<task_io_service>::context ctx(this);
 
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
     size_t n = 0;
- while (do_one(lock, 0, ec))
+ for (; do_one(lock, 0); lock.lock())
       if (n != (std::numeric_limits<size_t>::max)())
         ++n;
     return n;
@@ -136,11 +163,18 @@
   // Poll for one operation without blocking.
   size_t poll_one(boost::system::error_code& ec)
   {
+ ec = boost::system::error_code();
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ return 0;
+ }
+
     typename call_stack<task_io_service>::context ctx(this);
 
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
- return do_one(lock, 0, ec);
+ return do_one(lock, 0);
   }
 
   // Interrupt the event processing loop.
@@ -160,16 +194,14 @@
   // Notify that some work has started.
   void work_started()
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
     ++outstanding_work_;
   }
 
   // Notify that some work has finished.
   void work_finished()
   {
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (--outstanding_work_ == 0)
- stop_all_threads(lock);
+ stop();
   }
 
   // Request invocation of the given handler.
@@ -177,7 +209,10 @@
   void dispatch(Handler handler)
   {
     if (call_stack<task_io_service>::contains(this))
+ {
+ boost::asio::detail::fenced_block b;
       boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     else
       post(handler);
   }
@@ -187,29 +222,41 @@
   void post(Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
- handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
-
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
-
- // If the service has been shut down we silently discard the handler.
- if (shutdown_)
- return;
+ typedef completion_handler<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- // Add the handler to the end of the queue.
- handler_queue_.push(ptr.get());
+ post_immediate_completion(ptr.get());
     ptr.release();
+ }
 
- // An undelivered handler is treated as unfinished work.
- ++outstanding_work_;
+ // Request invocation of the given operation and return immediately. Assumes
+ // that work_started() has not yet been called for the operation.
+ void post_immediate_completion(operation* op)
+ {
+ work_started();
+ post_deferred_completion(op);
+ }
+
+ // Request invocation of the given operation and return immediately. Assumes
+ // that work_started() was previously called for the operation.
+ void post_deferred_completion(operation* op)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ op_queue_.push(op);
+ wake_one_thread_and_unlock(lock);
+ }
 
- // Wake up a thread to execute the handler.
- if (!interrupt_one_idle_thread(lock))
+ // Request invocation of the given operations and return immediately. Assumes
+ // that work_started() was previously called for each operation.
+ void post_deferred_completions(op_queue<operation>& ops)
+ {
+ if (!ops.empty())
     {
- if (!task_interrupted_ && task_)
- {
- task_interrupted_ = true;
- task_->interrupt();
- }
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ op_queue_.push(ops);
+ wake_one_thread_and_unlock(lock);
     }
   }
 
@@ -217,57 +264,60 @@
   struct idle_thread_info;
 
   size_t do_one(boost::asio::detail::mutex::scoped_lock& lock,
- idle_thread_info* this_idle_thread, boost::system::error_code& ec)
+ idle_thread_info* this_idle_thread)
   {
- if (outstanding_work_ == 0 && !stopped_)
- {
- stop_all_threads(lock);
- ec = boost::system::error_code();
- return 0;
- }
-
     bool polling = !this_idle_thread;
     bool task_has_run = false;
     while (!stopped_)
     {
- if (!handler_queue_.empty())
+ if (!op_queue_.empty())
       {
         // Prepare to execute first handler from queue.
- handler_queue::handler* h = handler_queue_.front();
- handler_queue_.pop();
+ operation* o = op_queue_.front();
+ op_queue_.pop();
+ bool more_handlers = (!op_queue_.empty());
 
- if (h == &task_handler_)
+ if (o == &task_operation_)
         {
- bool more_handlers = (!handler_queue_.empty());
           task_interrupted_ = more_handlers || polling;
 
           // If the task has already run and we're polling then we're done.
           if (task_has_run && polling)
           {
             task_interrupted_ = true;
- handler_queue_.push(&task_handler_);
- ec = boost::system::error_code();
+ op_queue_.push(&task_operation_);
             return 0;
           }
           task_has_run = true;
 
- lock.unlock();
- task_cleanup c(lock, *this);
-
- // Run the task. May throw an exception. Only block if the handler
- // queue is empty and we have an idle_thread_info object, otherwise
- // we want to return as soon as possible.
- task_->run(!more_handlers && !polling);
+ if (more_handlers)
+ wake_one_idle_thread_and_unlock(lock);
+ else
+ lock.unlock();
+
+ op_queue<operation> completed_ops;
+ task_cleanup c = { this, &lock, &completed_ops };
+ (void)c;
+
+ // Run the task. May throw an exception. Only block if the operation
+ // queue is empty and we're not polling, otherwise we want to return
+ // as soon as possible.
+ task_->run(!more_handlers && !polling, completed_ops);
         }
         else
         {
- lock.unlock();
- handler_cleanup c(lock, *this);
+ if (more_handlers)
+ wake_one_thread_and_unlock(lock);
+ else
+ lock.unlock();
+
+ // Ensure the count of outstanding work is decremented on block exit.
+ work_finished_on_block_exit on_exit = { this };
+ (void)on_exit;
 
- // Invoke the handler. May throw an exception.
- h->invoke(); // invoke() deletes the handler object
+ // Complete the operation. May throw an exception.
+ o->complete(*this); // deletes the operation object
 
- ec = boost::system::error_code();
           return 1;
         }
       }
@@ -281,12 +331,10 @@
       }
       else
       {
- ec = boost::system::error_code();
         return 0;
       }
     }
 
- ec = boost::system::error_code();
     return 0;
   }
 
@@ -295,7 +343,15 @@
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     stopped_ = true;
- interrupt_all_idle_threads(lock);
+
+ while (first_idle_thread_)
+ {
+ idle_thread_info* idle_thread = first_idle_thread_;
+ first_idle_thread_ = idle_thread->next;
+ idle_thread->next = 0;
+ idle_thread->wakeup_event.signal(lock);
+ }
+
     if (!task_interrupted_ && task_)
     {
       task_interrupted_ = true;
@@ -303,9 +359,10 @@
     }
   }
 
- // Interrupt a single idle thread. Returns true if a thread was interrupted,
- // false if no running thread could be found to interrupt.
- bool interrupt_one_idle_thread(
+ // Wakes a single idle thread and unlocks the mutex. Returns true if an idle
+ // thread was found. If there is no idle thread, returns false and leaves the
+ // mutex locked.
+ bool wake_one_idle_thread_and_unlock(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
     if (first_idle_thread_)
@@ -313,74 +370,56 @@
       idle_thread_info* idle_thread = first_idle_thread_;
       first_idle_thread_ = idle_thread->next;
       idle_thread->next = 0;
- idle_thread->wakeup_event.signal(lock);
+ idle_thread->wakeup_event.signal_and_unlock(lock);
       return true;
     }
     return false;
   }
 
- // Interrupt all idle threads.
- void interrupt_all_idle_threads(
+ // Wake a single idle thread, or the task, and always unlock the mutex.
+ void wake_one_thread_and_unlock(
       boost::asio::detail::mutex::scoped_lock& lock)
   {
- while (first_idle_thread_)
+ if (!wake_one_idle_thread_and_unlock(lock))
     {
- idle_thread_info* idle_thread = first_idle_thread_;
- first_idle_thread_ = idle_thread->next;
- idle_thread->next = 0;
- idle_thread->wakeup_event.signal(lock);
+ if (!task_interrupted_ && task_)
+ {
+ task_interrupted_ = true;
+ task_->interrupt();
+ }
+ lock.unlock();
     }
   }
 
   // Helper class to perform task-related operations on block exit.
- class task_cleanup;
- friend class task_cleanup;
- class task_cleanup
- {
- public:
- task_cleanup(boost::asio::detail::mutex::scoped_lock& lock,
- task_io_service& task_io_svc)
- : lock_(lock),
- task_io_service_(task_io_svc)
- {
- }
-
+ struct task_cleanup;
+ friend struct task_cleanup;
+ struct task_cleanup
+ {
     ~task_cleanup()
     {
- // Reinsert the task at the end of the handler queue.
- lock_.lock();
- task_io_service_.task_interrupted_ = true;
- task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
+ // Enqueue the completed operations and reinsert the task at the end of
+ // the operation queue.
+ lock_->lock();
+ task_io_service_->task_interrupted_ = true;
+ task_io_service_->op_queue_.push(*ops_);
+ task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
     }
 
- private:
- boost::asio::detail::mutex::scoped_lock& lock_;
- task_io_service& task_io_service_;
+ task_io_service* task_io_service_;
+ boost::asio::detail::mutex::scoped_lock* lock_;
+ op_queue<operation>* ops_;
   };
 
- // Helper class to perform handler-related operations on block exit.
- class handler_cleanup;
- friend class handler_cleanup;
- class handler_cleanup
+ // Helper class to call work_finished() on block exit.
+ struct work_finished_on_block_exit
   {
- public:
- handler_cleanup(boost::asio::detail::mutex::scoped_lock& lock,
- task_io_service& task_io_svc)
- : lock_(lock),
- task_io_service_(task_io_svc)
- {
- }
-
- ~handler_cleanup()
+ ~work_finished_on_block_exit()
     {
- lock_.lock();
- if (--task_io_service_.outstanding_work_ == 0)
- task_io_service_.stop_all_threads(lock_);
+ task_io_service_->work_finished();
     }
 
- private:
- boost::asio::detail::mutex::scoped_lock& lock_;
- task_io_service& task_io_service_;
+ task_io_service* task_io_service_;
   };
 
   // Mutex to protect access to internal data.
@@ -389,25 +428,20 @@
   // The task to be run by this service.
   Task* task_;
 
- // Handler object to represent the position of the task in the queue.
- class task_handler
- : public handler_queue::handler
+ // Operation object to represent the position of the task in the queue.
+ struct task_operation : public operation
   {
- public:
- task_handler()
- : handler_queue::handler(0, 0)
- {
- }
- } task_handler_;
+ task_operation() : operation(0) {}
+ } task_operation_;
 
   // Whether the task has been interrupted.
   bool task_interrupted_;
 
   // The count of unfinished work.
- int outstanding_work_;
+ boost::detail::atomic_count outstanding_work_;
 
   // The queue of handlers that are ready to be delivered.
- handler_queue handler_queue_;
+ op_queue<operation> op_queue_;
 
   // Flag to indicate that the dispatcher has been stopped.
   bool stopped_;
@@ -422,7 +456,7 @@
     idle_thread_info* next;
   };
 
- // The number of threads that are currently idle.
+ // The threads that are currently idle.
   idle_thread_info* first_idle_thread_;
 };
 
@@ -430,9 +464,6 @@
 } // namespace asio
 } // namespace boost
 
-#include <boost/system/error_code.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
-#endif // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
-
 #endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP

Deleted: branches/release/boost/asio/detail/task_io_service_2lock.hpp
==============================================================================
--- branches/release/boost/asio/detail/task_io_service_2lock.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
+++ (empty file)
@@ -1,475 +0,0 @@
-//
-// task_io_service_2lock.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_TASK_IO_SERVICE_2LOCK_HPP
-#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_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/io_service.hpp>
-#include <boost/asio/detail/call_stack.hpp>
-#include <boost/asio/detail/event.hpp>
-#include <boost/asio/detail/handler_alloc_helpers.hpp>
-#include <boost/asio/detail/handler_invoke_helpers.hpp>
-#include <boost/asio/detail/indirect_handler_queue.hpp>
-#include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/service_base.hpp>
-#include <boost/asio/detail/task_io_service_fwd.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-#include <boost/detail/atomic_count.hpp>
-#include <boost/system/error_code.hpp>
-#include <boost/asio/detail/pop_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-// An alternative task_io_service implementation based on a two-lock queue.
-
-template <typename Task>
-class task_io_service
- : public boost::asio::detail::service_base<task_io_service<Task> >
-{
-public:
- typedef indirect_handler_queue handler_queue;
-
- // Constructor.
- task_io_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
- front_mutex_(),
- back_mutex_(),
- task_(0),
- outstanding_work_(0),
- front_stopped_(false),
- back_stopped_(false),
- back_shutdown_(false),
- back_first_idle_thread_(0),
- back_task_thread_(0)
- {
- }
-
- void init(size_t /*concurrency_hint*/)
- {
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- back_shutdown_ = true;
- back_lock.unlock();
-
- // Destroy handler objects.
- while (handler_queue::handler* h = handler_queue_.pop())
- if (h != &task_handler_)
- h->destroy();
-
- // Reset to initial state.
- task_ = 0;
- }
-
- // Initialise the task, if required.
- void init_task()
- {
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- if (!back_shutdown_ && !task_)
- {
- task_ = &use_service<Task>(this->get_io_service());
- handler_queue_.push(&task_handler_);
- interrupt_one_idle_thread(back_lock);
- }
- }
-
- // Run the event loop until interrupted or no more work.
- size_t run(boost::system::error_code& ec)
- {
- if (outstanding_work_ == 0)
- {
- stop();
- ec = boost::system::error_code();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- idle_thread_info this_idle_thread;
- this_idle_thread.next = 0;
-
- size_t n = 0;
- while (do_one(&this_idle_thread, ec))
- if (n != (std::numeric_limits<size_t>::max)())
- ++n;
- return n;
- }
-
- // Run until interrupted or one operation is performed.
- size_t run_one(boost::system::error_code& ec)
- {
- if (outstanding_work_ == 0)
- {
- stop();
- ec = boost::system::error_code();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- idle_thread_info this_idle_thread;
- this_idle_thread.next = 0;
-
- return do_one(&this_idle_thread, ec);
- }
-
- // Poll for operations without blocking.
- size_t poll(boost::system::error_code& ec)
- {
- if (outstanding_work_ == 0)
- {
- stop();
- ec = boost::system::error_code();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- size_t n = 0;
- while (do_one(0, ec))
- if (n != (std::numeric_limits<size_t>::max)())
- ++n;
- return n;
- }
-
- // Poll for one operation without blocking.
- size_t poll_one(boost::system::error_code& ec)
- {
- if (outstanding_work_ == 0)
- {
- stop();
- ec = boost::system::error_code();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- return do_one(0, ec);
- }
-
- // Interrupt the event processing loop.
- void stop()
- {
- boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
- front_stopped_ = true;
- front_lock.unlock();
-
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- back_stopped_ = true;
- interrupt_all_idle_threads(back_lock);
- }
-
- // Reset in preparation for a subsequent run invocation.
- void reset()
- {
- boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
- front_stopped_ = false;
- front_lock.unlock();
-
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- back_stopped_ = false;
- }
-
- // Notify that some work has started.
- void work_started()
- {
- ++outstanding_work_;
- }
-
- // Notify that some work has finished.
- void work_finished()
- {
- if (--outstanding_work_ == 0)
- stop();
- }
-
- // Request invocation of the given handler.
- template <typename Handler>
- void dispatch(Handler handler)
- {
- if (call_stack<task_io_service>::contains(this))
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- else
- post(handler);
- }
-
- // Request invocation of the given handler and return immediately.
- template <typename Handler>
- void post(Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
-
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
-
- // If the service has been shut down we silently discard the handler.
- if (back_shutdown_)
- return;
-
- // Add the handler to the end of the queue.
- handler_queue_.push(ptr.get());
- ptr.release();
-
- // An undelivered handler is treated as unfinished work.
- ++outstanding_work_;
-
- // Wake up a thread to execute the handler.
- interrupt_one_idle_thread(back_lock);
- }
-
-private:
- struct idle_thread_info;
-
- size_t do_one(idle_thread_info* this_idle_thread,
- boost::system::error_code& ec)
- {
- bool task_has_run = false;
- for (;;)
- {
- // The front lock must be held before we can pop items from the queue.
- boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
- if (front_stopped_)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
- if (handler_queue::handler* h = handler_queue_.pop())
- {
- if (h == &task_handler_)
- {
- bool more_handlers = handler_queue_.poppable();
- unsigned long front_version = handler_queue_.front_version();
- front_lock.unlock();
-
- // The task is always added to the back of the queue when we exit
- // this block.
- task_cleanup c(*this);
-
- // If we're polling and the task has already run then we're done.
- bool polling = !this_idle_thread;
- if (task_has_run && polling)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
- // If we're considering going idle we need to check whether the queue
- // is still empty. If it is, add the thread to the list of idle
- // threads.
- if (!more_handlers && !polling)
- {
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- if (back_stopped_)
- {
- ec = boost::system::error_code();
- return 0;
- }
- else if (front_version == handler_queue_.back_version())
- {
- back_task_thread_ = this_idle_thread;
- }
- else
- {
- more_handlers = true;
- }
- }
-
- // Run the task. May throw an exception. Only block if the handler
- // queue is empty and we're not polling, otherwise we want to return
- // as soon as possible.
- task_has_run = true;
- task_->run(!more_handlers && !polling);
- }
- else
- {
- front_lock.unlock();
- handler_cleanup c(*this);
-
- // Invoke the handler. May throw an exception.
- h->invoke(); // invoke() deletes the handler object
-
- ec = boost::system::error_code();
- return 1;
- }
- }
- else if (this_idle_thread)
- {
- unsigned long front_version = handler_queue_.front_version();
- front_lock.unlock();
-
- // If we're considering going idle we need to check whether the queue
- // is still empty. If it is, add the thread to the list of idle
- // threads.
- boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
- if (back_stopped_)
- {
- ec = boost::system::error_code();
- return 0;
- }
- else if (front_version == handler_queue_.back_version())
- {
- this_idle_thread->next = back_first_idle_thread_;
- back_first_idle_thread_ = this_idle_thread;
- this_idle_thread->wakeup_event.clear(back_lock);
- this_idle_thread->wakeup_event.wait(back_lock);
- }
- }
- else
- {
- ec = boost::system::error_code();
- return 0;
- }
- }
- }
-
- // Interrupt a single idle thread.
- void interrupt_one_idle_thread(
- boost::asio::detail::mutex::scoped_lock& back_lock)
- {
- if (back_first_idle_thread_)
- {
- idle_thread_info* idle_thread = back_first_idle_thread_;
- back_first_idle_thread_ = idle_thread->next;
- idle_thread->next = 0;
- idle_thread->wakeup_event.signal(back_lock);
- }
- else if (back_task_thread_ && task_)
- {
- back_task_thread_ = 0;
- task_->interrupt();
- }
- }
-
- // Interrupt all idle threads.
- void interrupt_all_idle_threads(
- boost::asio::detail::mutex::scoped_lock& back_lock)
- {
- while (back_first_idle_thread_)
- {
- idle_thread_info* idle_thread = back_first_idle_thread_;
- back_first_idle_thread_ = idle_thread->next;
- idle_thread->next = 0;
- idle_thread->wakeup_event.signal(back_lock);
- }
-
- if (back_task_thread_ && task_)
- {
- back_task_thread_ = 0;
- task_->interrupt();
- }
- }
-
- // Helper class to perform task-related operations on block exit.
- class task_cleanup;
- friend class task_cleanup;
- class task_cleanup
- {
- public:
- task_cleanup(task_io_service& task_io_svc)
- : task_io_service_(task_io_svc)
- {
- }
-
- ~task_cleanup()
- {
- // Reinsert the task at the end of the handler queue.
- boost::asio::detail::mutex::scoped_lock back_lock(
- task_io_service_.back_mutex_);
- task_io_service_.back_task_thread_ = 0;
- task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
- }
-
- private:
- task_io_service& task_io_service_;
- };
-
- // Helper class to perform handler-related operations on block exit.
- class handler_cleanup
- {
- public:
- handler_cleanup(task_io_service& task_io_svc)
- : task_io_service_(task_io_svc)
- {
- }
-
- ~handler_cleanup()
- {
- task_io_service_.work_finished();
- }
-
- private:
- task_io_service& task_io_service_;
- };
-
- // Mutexes to protect access to internal data.
- boost::asio::detail::mutex front_mutex_;
- boost::asio::detail::mutex back_mutex_;
-
- // The task to be run by this service.
- Task* task_;
-
- // Handler object to represent the position of the task in the queue.
- class task_handler
- : public handler_queue::handler
- {
- public:
- task_handler()
- : handler_queue::handler(0, 0)
- {
- }
- } task_handler_;
-
- // The count of unfinished work.
- boost::detail::atomic_count outstanding_work_;
-
- // The queue of handlers that are ready to be delivered.
- handler_queue handler_queue_;
-
- // Flag to indicate that the dispatcher has been stopped.
- bool front_stopped_;
- bool back_stopped_;
-
- // Flag to indicate that the dispatcher has been shut down.
- bool back_shutdown_;
-
- // Structure containing information about an idle thread.
- struct idle_thread_info
- {
- event wakeup_event;
- idle_thread_info* next;
- };
-
- // The number of threads that are currently idle.
- idle_thread_info* back_first_idle_thread_;
-
- // The thread that is currently blocked on the task.
- idle_thread_info* back_task_thread_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP

Modified: branches/release/boost/asio/detail/timer_queue.hpp
==============================================================================
--- branches/release/boost/asio/detail/timer_queue.hpp (original)
+++ branches/release/boost/asio/detail/timer_queue.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -19,7 +19,6 @@
 
 #include <boost/asio/detail/push_options.hpp>
 #include <cstddef>
-#include <functional>
 #include <memory>
 #include <vector>
 #include <boost/config.hpp>
@@ -27,9 +26,9 @@
 #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>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 
 namespace boost {
@@ -50,50 +49,36 @@
   // Constructor.
   timer_queue()
     : timers_(),
- heap_(),
- cancelled_timers_(0),
- complete_timers_(0)
+ heap_()
   {
   }
 
   // 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.
- template <typename Handler>
- bool enqueue_timer(const time_type& time, Handler handler, void* token)
+ bool enqueue_timer(const time_type& time, timer_op* op, void* token)
   {
     // 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);
 
- // Create a new timer object.
- typedef timer<Handler> timer_type;
- typedef handler_alloc_traits<Handler, timer_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> new_timer(raw_ptr, time, handler, token);
-
     // Insert the new timer into the hash.
- typedef typename hash_map<void*, timer_base*>::iterator iterator;
- typedef typename hash_map<void*, timer_base*>::value_type value_type;
+ 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, new_timer.get()));
- if (!result.second)
- {
- result.first->second->prev_ = new_timer.get();
- new_timer.get()->next_ = result.first->second;
- result.first->second = new_timer.get();
+ timers_.insert(value_type(token, timer()));
+ result.first->second.op_queue_.push(op);
+ if (result.second)
+ {
+ // 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);
     }
 
- // Put the timer at the correct position in the heap.
- new_timer.get()->heap_index_ = heap_.size();
- heap_.push_back(new_timer.get());
- up_heap(heap_.size() - 1);
- bool is_first = (heap_[0] == new_timer.get());
-
- // Ownership of the timer is transferred to the timer queue.
- new_timer.release();
-
- return is_first;
+ return (heap_[0] == &result.first->second);
   }
 
   // Whether there are no timers in the queue.
@@ -103,226 +88,106 @@
   }
 
   // Get the time for the timer that is earliest in the queue.
- virtual boost::posix_time::time_duration wait_duration() const
+ virtual long wait_duration_msec(long max_duration) const
   {
     if (heap_.empty())
- return boost::posix_time::pos_infin;
- return Time_Traits::to_posix_duration(
+ return max_duration;
+
+ boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
         Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
- }
 
- // Dispatch the timers that are earlier than the specified time.
- virtual void dispatch_timers()
- {
- const time_type now = Time_Traits::now();
- while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
- {
- timer_base* t = heap_[0];
- remove_timer(t);
- t->result_ = boost::system::error_code();
- t->prev_ = 0;
- t->next_ = complete_timers_;
- complete_timers_ = t;
- }
- }
+ if (duration > boost::posix_time::milliseconds(max_duration))
+ duration = boost::posix_time::milliseconds(max_duration);
+ else if (duration < boost::posix_time::milliseconds(0))
+ duration = boost::posix_time::milliseconds(0);
 
- // Cancel the timers with the given token. Any timers pending for the token
- // will be notified that they have been cancelled next time
- // dispatch_cancellations is called. Returns the number of timers that were
- // cancelled.
- std::size_t cancel_timer(void* timer_token)
- {
- std::size_t num_cancelled = 0;
- typedef typename hash_map<void*, timer_base*>::iterator iterator;
- iterator it = timers_.find(timer_token);
- if (it != timers_.end())
- {
- timer_base* t = it->second;
- while (t)
- {
- timer_base* next = t->next_;
- remove_timer(t);
- t->prev_ = 0;
- t->next_ = cancelled_timers_;
- cancelled_timers_ = t;
- t = next;
- ++num_cancelled;
- }
- }
- return num_cancelled;
+ return duration.total_milliseconds();
   }
 
- // Dispatch any pending cancels for timers.
- virtual void dispatch_cancellations()
+ // Get the time for the timer that is earliest in the queue.
+ virtual long wait_duration_usec(long max_duration) const
   {
- while (cancelled_timers_)
- {
- timer_base* this_timer = cancelled_timers_;
- this_timer->result_ = boost::asio::error::operation_aborted;
- cancelled_timers_ = this_timer->next_;
- this_timer->next_ = complete_timers_;
- complete_timers_ = this_timer;
- }
+ if (heap_.empty())
+ return max_duration;
+
+ boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
+ Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+
+ if (duration > boost::posix_time::microseconds(max_duration))
+ duration = boost::posix_time::microseconds(max_duration);
+ else if (duration < boost::posix_time::microseconds(0))
+ duration = boost::posix_time::microseconds(0);
+
+ return duration.total_microseconds();
   }
 
- // Complete any timers that are waiting to be completed.
- virtual void complete_timers()
+ // Dequeue all timers not later than the current time.
+ virtual void get_ready_timers(op_queue<operation>& ops)
   {
- while (complete_timers_)
+ const time_type now = Time_Traits::now();
+ while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
     {
- timer_base* this_timer = complete_timers_;
- complete_timers_ = this_timer->next_;
- this_timer->next_ = 0;
- this_timer->complete();
+ timer* t = heap_[0];
+ ops.push(t->op_queue_);
+ remove_timer(t);
     }
   }
 
- // Destroy all timers.
- virtual void destroy_timers()
+ // Dequeue all timers.
+ virtual void get_all_timers(op_queue<operation>& ops)
   {
- typename hash_map<void*, timer_base*>::iterator i = timers_.begin();
- typename hash_map<void*, timer_base*>::iterator end = timers_.end();
+ typename hash_map<void*, timer>::iterator i = timers_.begin();
+ typename hash_map<void*, timer>::iterator end = timers_.end();
     while (i != end)
     {
- timer_base* t = i->second;
- typename hash_map<void*, timer_base*>::iterator old_i = i++;
+ ops.push(i->second.op_queue_);
+ typename hash_map<void*, timer>::iterator old_i = i++;
       timers_.erase(old_i);
- destroy_timer_list(t);
     }
+
     heap_.clear();
     timers_.clear();
- destroy_timer_list(cancelled_timers_);
- destroy_timer_list(complete_timers_);
   }
 
-private:
- // Base class for timer operations. Function pointers are used instead of
- // virtual functions to avoid the associated overhead.
- class timer_base
- {
- public:
- // Delete the timer and post the handler.
- void complete()
- {
- complete_func_(this, result_);
- }
-
- // Delete the timer.
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- typedef void (*complete_func_type)(timer_base*,
- const boost::system::error_code&);
- typedef void (*destroy_func_type)(timer_base*);
-
- // Constructor.
- timer_base(complete_func_type complete_func, destroy_func_type destroy_func,
- const time_type& time, void* token)
- : complete_func_(complete_func),
- destroy_func_(destroy_func),
- time_(time),
- token_(token),
- next_(0),
- prev_(0),
- heap_index_(
- std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
- {
- }
-
- // Prevent deletion through this type.
- ~timer_base()
+ // Cancel and dequeue the timers with the given token.
+ std::size_t cancel_timer(void* timer_token, 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())
     {
+ while (timer_op* op = it->second.op_queue_.front())
+ {
+ op->ec_ = boost::asio::error::operation_aborted;
+ it->second.op_queue_.pop();
+ ops.push(op);
+ ++num_cancelled;
+ }
+ remove_timer(&it->second);
     }
+ return num_cancelled;
+ }
 
- private:
- friend class timer_queue<Time_Traits>;
-
- // The function to be called to delete the timer and post the handler.
- complete_func_type complete_func_;
-
- // The function to be called to delete the timer.
- destroy_func_type destroy_func_;
-
- // The result of the timer operation.
- boost::system::error_code result_;
+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 token associated with the timer.
- void* token_;
-
- // The next timer known to the queue.
- timer_base* next_;
-
- // The previous timer known to the queue.
- timer_base* prev_;
+ // The operations waiting on the timer.
+ op_queue<timer_op> op_queue_;
 
     // The index of the timer in the heap.
     size_t heap_index_;
- };
 
- // Adaptor class template for using handlers in timers.
- template <typename Handler>
- class timer
- : public timer_base
- {
- public:
- // Constructor.
- timer(const time_type& time, Handler handler, void* token)
- : timer_base(&timer<Handler>::complete_handler,
- &timer<Handler>::destroy_handler, time, token),
- handler_(handler)
- {
- }
-
- // Delete the timer and post the handler.
- static void complete_handler(timer_base* base,
- const boost::system::error_code& result)
- {
- // Take ownership of the timer object.
- typedef timer<Handler> this_type;
- this_type* this_timer(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
-
- // Make a copy of the error_code and the handler so that the memory can
- // be deallocated before the upcall is made.
- boost::system::error_code ec(result);
- Handler handler(this_timer->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- handler(ec);
- }
-
- // Delete the timer.
- static void destroy_handler(timer_base* base)
- {
- // Take ownership of the timer object.
- typedef timer<Handler> this_type;
- this_type* this_timer(static_cast<this_type*>(base));
- typedef handler_alloc_traits<Handler, this_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(this_timer->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
-
- private:
- Handler handler_;
+ // The token associated with the timer.
+ void* token_;
   };
 
   // Move the item at the given index up the heap to its correct position.
@@ -359,7 +224,7 @@
   // Swap two entries in the heap.
   void swap_heap(size_t index1, size_t index2)
   {
- timer_base* tmp = heap_[index1];
+ timer* tmp = heap_[index1];
     heap_[index1] = heap_[index2];
     heap_[index2] = tmp;
     heap_[index1]->heap_index_ = index1;
@@ -367,7 +232,7 @@
   }
 
   // Remove a timer from the heap and list of timers.
- void remove_timer(timer_base* t)
+ void remove_timer(timer* t)
   {
     // Remove the timer from the heap.
     size_t index = t->heap_index_;
@@ -391,44 +256,17 @@
     }
 
     // Remove the timer from the hash.
- typedef typename hash_map<void*, timer_base*>::iterator iterator;
+ typedef typename hash_map<void*, timer>::iterator iterator;
     iterator it = timers_.find(t->token_);
     if (it != timers_.end())
- {
- if (it->second == t)
- it->second = t->next_;
- if (t->prev_)
- t->prev_->next_ = t->next_;
- if (t->next_)
- t->next_->prev_ = t->prev_;
- if (it->second == 0)
- timers_.erase(it);
- }
- }
-
- // Destroy all timers in a linked list.
- void destroy_timer_list(timer_base*& t)
- {
- while (t)
- {
- timer_base* next = t->next_;
- t->next_ = 0;
- t->destroy();
- t = next;
- }
+ timers_.erase(it);
   }
 
   // A hash of timer token to linked lists of timers.
- hash_map<void*, timer_base*> timers_;
+ hash_map<void*, timer> timers_;
 
   // The heap of timers, with the earliest timer at the front.
- std::vector<timer_base*> heap_;
-
- // The list of timers to be cancelled.
- timer_base* cancelled_timers_;
-
- // The list of timers waiting to be completed.
- timer_base* complete_timers_;
+ std::vector<timer*> heap_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/timer_queue_base.hpp
==============================================================================
--- branches/release/boost/asio/detail/timer_queue_base.hpp (original)
+++ branches/release/boost/asio/detail/timer_queue_base.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -17,13 +17,9 @@
 
 #include <boost/asio/detail/push_options.hpp>
 
-#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.
-
-#include <boost/asio/detail/push_options.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/asio/detail/pop_options.hpp>
-
 #include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/operation.hpp>
 
 namespace boost {
 namespace asio {
@@ -33,6 +29,9 @@
   : private noncopyable
 {
 public:
+ // Constructor.
+ timer_queue_base() : next_(0) {}
+
   // Destructor.
   virtual ~timer_queue_base() {}
 
@@ -40,19 +39,22 @@
   virtual bool empty() const = 0;
 
   // Get the time to wait until the next timer.
- virtual boost::posix_time::time_duration wait_duration() const = 0;
+ virtual long wait_duration_msec(long max_duration) const = 0;
+
+ // Get the time to wait until the next timer.
+ virtual long wait_duration_usec(long max_duration) const = 0;
 
- // Dispatch all ready timers.
- virtual void dispatch_timers() = 0;
+ // Dequeue all ready timers.
+ virtual void get_ready_timers(op_queue<operation>& ops) = 0;
 
- // Dispatch any pending cancels for timers.
- virtual void dispatch_cancellations() = 0;
+ // Dequeue all timers.
+ virtual void get_all_timers(op_queue<operation>& ops) = 0;
 
- // Complete all timers that are waiting to be completed.
- virtual void complete_timers() = 0;
+private:
+ friend class timer_queue_set;
 
- // Destroy all timers.
- virtual void destroy_timers() = 0;
+ // Next timer queue in the set.
+ timer_queue_base* next_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/win_event.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_event.hpp (original)
+++ branches/release/boost/asio/detail/win_event.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -71,6 +71,15 @@
     ::SetEvent(event_);
   }
 
+ // Signal the event and unlock the mutex.
+ template <typename Lock>
+ void signal_and_unlock(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ lock.unlock();
+ ::SetEvent(event_);
+ }
+
   // Reset the event.
   template <typename Lock>
   void clear(Lock& lock)

Modified: branches/release/boost/asio/detail/win_iocp_handle_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_handle_service.hpp (original)
+++ branches/release/boost/asio/detail/win_iocp_handle_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -26,13 +26,14 @@
 #include <boost/cstdint.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
-#include <boost/asio/buffer.hpp>
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/operation.hpp>
 #include <boost/asio/detail/win_iocp_io_service.hpp>
 
 namespace boost {
@@ -40,12 +41,8 @@
 namespace detail {
 
 class win_iocp_handle_service
- : public boost::asio::detail::service_base<win_iocp_handle_service>
 {
 public:
- // Base class for all operations.
- typedef win_iocp_io_service::operation operation;
-
   // The native type of a stream handle.
   typedef HANDLE native_type;
 
@@ -81,8 +78,7 @@
   };
 
   win_iocp_handle_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<win_iocp_handle_service>(io_service),
- iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+ : iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
       mutex_(),
       impl_list_(0)
   {
@@ -307,16 +303,9 @@
       return 0;
     }
 
- // Find first buffer of non-zero length.
- boost::asio::const_buffer buffer;
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- for (DWORD i = 0; iter != end; ++iter, ++i)
- {
- buffer = boost::asio::const_buffer(*iter);
- if (boost::asio::buffer_size(buffer) != 0)
- break;
- }
+ boost::asio::const_buffer buffer =
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::first(buffers);
 
     // A request to write 0 bytes on a handle is a no-op.
     if (boost::asio::buffer_size(buffer) == 0)
@@ -365,79 +354,48 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class write_operation
- : public operation
+ class write_op : public operation
   {
   public:
- write_operation(win_iocp_io_service& io_service,
- const ConstBufferSequence& buffers, Handler handler)
- : operation(io_service,
- &write_operation<ConstBufferSequence, Handler>::do_completion_impl,
- &write_operation<ConstBufferSequence, Handler>::destroy_impl),
- work_(io_service.get_io_service()),
+ write_op(const ConstBufferSequence& buffers, Handler handler)
+ : operation(&write_op::do_complete),
         buffers_(buffers),
         handler_(handler)
     {
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef write_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ write_op* o(static_cast<write_op*>(base));
+ typedef handler_alloc_traits<Handler, write_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename ConstBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename ConstBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::const_buffer buffer(*iter);
- boost::asio::buffer_cast<const char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- boost_asio_handler_invoke_helpers::invoke(
- bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef write_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
- boost::asio::io_service::work work_;
+ private:
     ConstBufferSequence buffers_;
     Handler handler_;
   };
@@ -457,65 +415,16 @@
   void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
       const ConstBufferSequence& buffers, Handler handler)
   {
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-
     // Allocate and construct an operation to wrap the handler.
- typedef write_operation<ConstBufferSequence, Handler> value_type;
+ typedef write_op<ConstBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
-
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
-
- // Find first buffer of non-zero length.
- boost::asio::const_buffer buffer;
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- for (DWORD i = 0; iter != end; ++iter, ++i)
- {
- buffer = boost::asio::const_buffer(*iter);
- if (boost::asio::buffer_size(buffer) != 0)
- break;
- }
-
- // A request to write 0 bytes on a handle is a no-op.
- if (boost::asio::buffer_size(buffer) == 0)
- {
- ptr.get()->on_immediate_completion(0, 0);
- ptr.release();
- return;
- }
-
- // Write the data.
- DWORD bytes_transferred = 0;
- ptr.get()->Offset = offset & 0xFFFFFFFF;
- ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::WriteFile(impl.handle_,
- boost::asio::buffer_cast<LPCVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)),
- &bytes_transferred, ptr.get());
- DWORD last_error = ::GetLastError();
+ handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler);
 
- // Check if the operation completed immediately.
- if (!ok && last_error != ERROR_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_write_op(impl, offset,
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::first(buffers), ptr.get());
+ ptr.release();
   }
 
   // Read some data. Returns the number of bytes received.
@@ -537,16 +446,9 @@
       return 0;
     }
     
- // Find first buffer of non-zero length.
- boost::asio::mutable_buffer buffer;
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- for (DWORD i = 0; iter != end; ++iter, ++i)
- {
- buffer = boost::asio::mutable_buffer(*iter);
- if (boost::asio::buffer_size(buffer) != 0)
- break;
- }
+ boost::asio::mutable_buffer buffer =
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::first(buffers);
 
     // A request to read 0 bytes on a stream handle is a no-op.
     if (boost::asio::buffer_size(buffer) == 0)
@@ -609,89 +511,54 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class read_operation
- : public operation
+ class read_op : public operation
   {
   public:
- read_operation(win_iocp_io_service& io_service,
- const MutableBufferSequence& buffers, Handler handler)
- : operation(io_service,
- &read_operation<
- MutableBufferSequence, Handler>::do_completion_impl,
- &read_operation<
- MutableBufferSequence, Handler>::destroy_impl),
- work_(io_service.get_io_service()),
+ read_op(const MutableBufferSequence& buffers, Handler handler)
+ : operation(&read_op::do_complete),
         buffers_(buffers),
         handler_(handler)
     {
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef read_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ read_op* o(static_cast<read_op*>(base));
+ typedef handler_alloc_traits<Handler, read_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename MutableBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename MutableBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::mutable_buffer buffer(*iter);
- boost::asio::buffer_cast<char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Check for the end-of-file condition.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF)
- {
- ec = boost::asio::error::eof;
- }
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost_asio_handler_invoke_helpers::invoke(
- bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef read_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef boost::asio::detail::handler_alloc_traits<
- Handler, op_type> alloc_traits;
- boost::asio::detail::handler_ptr<alloc_traits> ptr(
- handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_HANDLE_EOF)
+ {
+ ec = boost::asio::error::eof;
+ }
 
- // Free the memory associated with the handler.
- ptr.reset();
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
- boost::asio::io_service::work work_;
+ private:
     MutableBufferSequence buffers_;
     Handler handler_;
   };
@@ -712,63 +579,16 @@
   void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
       const MutableBufferSequence& buffers, Handler handler)
   {
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-
     // Allocate and construct an operation to wrap the handler.
- typedef read_operation<MutableBufferSequence, Handler> value_type;
+ typedef read_op<MutableBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
-
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
-
- // Find first buffer of non-zero length.
- boost::asio::mutable_buffer buffer;
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- for (DWORD i = 0; iter != end; ++iter, ++i)
- {
- buffer = boost::asio::mutable_buffer(*iter);
- if (boost::asio::buffer_size(buffer) != 0)
- break;
- }
+ handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler);
 
- // A request to receive 0 bytes on a stream handle is a no-op.
- if (boost::asio::buffer_size(buffer) == 0)
- {
- ptr.get()->on_immediate_completion(0, 0);
- ptr.release();
- return;
- }
-
- // Read some data.
- DWORD bytes_transferred = 0;
- ptr.get()->Offset = offset & 0xFFFFFFFF;
- ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::ReadFile(impl.handle_,
- boost::asio::buffer_cast<LPVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)),
- &bytes_transferred, ptr.get());
- DWORD last_error = ::GetLastError();
- if (!ok && last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_read_op(impl, offset,
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::first(buffers), ptr.get());
+ ptr.release();
   }
 
 private:
@@ -794,6 +614,93 @@
   void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
       const null_buffers& buffers, Handler handler);
 
+ // Helper function to start a write operation.
+ void start_write_op(implementation_type& impl, boost::uint64_t offset,
+ const boost::asio::const_buffer& buffer, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
+
+ if (!is_open(impl))
+ {
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ }
+ else if (boost::asio::buffer_size(buffer) == 0)
+ {
+ // A request to write 0 bytes on a handle is a no-op.
+ iocp_service_.on_completion(op);
+ }
+ else
+ {
+ DWORD bytes_transferred = 0;
+ op->Offset = offset & 0xFFFFFFFF;
+ op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+ BOOL ok = ::WriteFile(impl.handle_,
+ boost::asio::buffer_cast<LPCVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ &bytes_transferred, op);
+ DWORD last_error = ::GetLastError();
+ if (!ok && last_error != ERROR_IO_PENDING
+ && last_error != ERROR_MORE_DATA)
+ {
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ }
+ else
+ {
+ iocp_service_.on_pending(op);
+ }
+ }
+ }
+
+ // Helper function to start a read operation.
+ void start_read_op(implementation_type& impl, boost::uint64_t offset,
+ const boost::asio::mutable_buffer& buffer, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
+
+ if (!is_open(impl))
+ {
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ }
+ else if (boost::asio::buffer_size(buffer) == 0)
+ {
+ // A request to read 0 bytes on a handle is a no-op.
+ iocp_service_.on_completion(op);
+ }
+ else
+ {
+ DWORD bytes_transferred = 0;
+ op->Offset = offset & 0xFFFFFFFF;
+ op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+ BOOL ok = ::ReadFile(impl.handle_,
+ boost::asio::buffer_cast<LPVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ &bytes_transferred, op);
+ DWORD last_error = ::GetLastError();
+ if (!ok && last_error != ERROR_IO_PENDING
+ && last_error != ERROR_MORE_DATA)
+ {
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ }
+ else
+ {
+ iocp_service_.on_pending(op);
+ }
+ }
+ }
+
+ // Update the ID of the thread from which cancellation is safe.
+ void update_cancellation_thread_id()
+ {
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ if (impl.safe_cancellation_thread_id_ == 0)
+ impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+ else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+ impl.safe_cancellation_thread_id_ = ~DWORD(0);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ }
+
   // Helper function to close a handle when the associated object is being
   // destroyed.
   void close_for_destruction(implementation_type& impl)

Modified: branches/release/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_io_service.hpp (original)
+++ branches/release/boost/asio/detail/win_iocp_io_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -29,122 +29,37 @@
 
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/completion_handler.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/op_queue.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_queue.hpp>
-#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/timer_queue_fwd.hpp>
+#include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/win_iocp_operation.hpp>
 
 namespace boost {
 namespace asio {
 namespace detail {
 
+class timer_op;
+
 class win_iocp_io_service
   : public boost::asio::detail::service_base<win_iocp_io_service>
 {
 public:
- // Base class for all operations. A function pointer is used instead of
- // virtual functions to avoid the associated overhead.
- //
- // This class inherits from OVERLAPPED so that we can downcast to get back to
- // the operation pointer from the LPOVERLAPPED out parameter of
- // GetQueuedCompletionStatus.
- class operation;
- friend class operation;
- class operation
- : public OVERLAPPED
- {
- public:
- typedef void (*invoke_func_type)(operation*, DWORD, size_t);
- typedef void (*destroy_func_type)(operation*);
-
- operation(win_iocp_io_service& iocp_service,
- invoke_func_type invoke_func, destroy_func_type destroy_func)
- : iocp_service_(iocp_service),
- ready_(0),
- last_error_(~DWORD(0)),
- bytes_transferred_(0),
- invoke_func_(invoke_func),
- destroy_func_(destroy_func)
- {
- Internal = 0;
- InternalHigh = 0;
- Offset = 0;
- OffsetHigh = 0;
- hEvent = 0;
-
- ::InterlockedIncrement(&iocp_service_.outstanding_operations_);
- }
-
- void reset()
- {
- Internal = 0;
- InternalHigh = 0;
- Offset = 0;
- OffsetHigh = 0;
- hEvent = 0;
- ready_ = 0;
- last_error_ = ~DWORD(0);
- bytes_transferred_ = 0;
- }
-
- void on_pending()
- {
- if (::InterlockedCompareExchange(&ready_, 1, 0) == 1)
- iocp_service_.post_completion(this, last_error_, bytes_transferred_);
- }
-
- void on_immediate_completion(DWORD last_error, DWORD bytes_transferred)
- {
- ready_ = 1;
- iocp_service_.post_completion(this, last_error, bytes_transferred);
- }
-
- bool on_completion(DWORD last_error, DWORD bytes_transferred)
- {
- if (last_error_ == ~DWORD(0))
- {
- last_error_ = last_error;
- bytes_transferred_ = bytes_transferred;
- }
-
- if (::InterlockedCompareExchange(&ready_, 1, 0) == 1)
- {
- invoke_func_(this, last_error_, bytes_transferred_);
- return true;
- }
-
- return false;
- }
-
- void destroy()
- {
- destroy_func_(this);
- }
-
- protected:
- // Prevent deletion through this type.
- ~operation()
- {
- ::InterlockedDecrement(&iocp_service_.outstanding_operations_);
- }
-
- private:
- win_iocp_io_service& iocp_service_;
- long ready_;
- DWORD last_error_;
- DWORD bytes_transferred_;
- invoke_func_type invoke_func_;
- destroy_func_type destroy_func_;
- };
+ typedef win_iocp_operation operation;
 
   // Constructor.
   win_iocp_io_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<win_iocp_io_service>(io_service),
       iocp_(),
       outstanding_work_(0),
- outstanding_operations_(0),
       stopped_(0),
       shutdown_(0),
       timer_thread_(0),
@@ -172,24 +87,34 @@
   {
     ::InterlockedExchange(&shutdown_, 1);
 
- while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0)
+ while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
     {
- DWORD bytes_transferred = 0;
-#if defined(WINVER) && (WINVER < 0x0500)
- DWORD completion_key = 0;
-#else
- DWORD_PTR completion_key = 0;
-#endif
- LPOVERLAPPED overlapped = 0;
- ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
- &completion_key, &overlapped, INFINITE);
- if (overlapped)
- static_cast<operation*>(overlapped)->destroy();
+ op_queue<operation> ops;
+ timer_queues_.get_all_timers(ops);
+ ops.push(completed_ops_);
+ if (!ops.empty())
+ {
+ while (operation* op = ops.front())
+ {
+ ops.pop();
+ ::InterlockedDecrement(&outstanding_work_);
+ op->destroy();
+ }
+ }
+ else
+ {
+ DWORD bytes_transferred = 0;
+ dword_ptr_t completion_key = 0;
+ LPOVERLAPPED overlapped = 0;
+ ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+ &completion_key, &overlapped, max_timeout);
+ if (overlapped)
+ {
+ ::InterlockedDecrement(&outstanding_work_);
+ static_cast<operation*>(overlapped)->destroy();
+ }
+ }
     }
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- timer_queues_[i]->destroy_timers();
- timer_queues_.clear();
   }
 
   // Initialise the task. Nothing to do here.
@@ -219,6 +144,7 @@
   {
     if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
     {
+ stop();
       ec = boost::system::error_code();
       return 0;
     }
@@ -237,6 +163,7 @@
   {
     if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
     {
+ stop();
       ec = boost::system::error_code();
       return 0;
     }
@@ -251,6 +178,7 @@
   {
     if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
     {
+ stop();
       ec = boost::system::error_code();
       return 0;
     }
@@ -269,6 +197,7 @@
   {
     if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
     {
+ stop();
       ec = boost::system::error_code();
       return 0;
     }
@@ -319,7 +248,10 @@
   void dispatch(Handler handler)
   {
     if (call_stack<win_iocp_io_service>::contains(this))
+ {
+ boost::asio::detail::fenced_block b;
       boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     else
       post(handler);
   }
@@ -328,37 +260,128 @@
   template <typename Handler>
   void post(Handler handler)
   {
- // If the service has been shut down we silently discard the handler.
- if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
- return;
-
     // Allocate and construct an operation to wrap the handler.
- typedef handler_operation<Handler> value_type;
+ typedef completion_handler<Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, *this, handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+ post_immediate_completion(ptr.get());
+ ptr.release();
+ }
+
+ // Request invocation of the given operation and return immediately. Assumes
+ // that work_started() has not yet been called for the operation.
+ void post_immediate_completion(operation* op)
+ {
+ work_started();
+ post_deferred_completion(op);
+ }
+
+ // Request invocation of the given operation and return immediately. Assumes
+ // that work_started() was previously called for the operation.
+ void post_deferred_completion(operation* op)
+ {
+ // Flag the operation as ready.
+ op->ready_ = 1;
 
     // Enqueue the operation on the I/O completion port.
- ptr.get()->on_immediate_completion(0, 0);
+ if (!::PostQueuedCompletionStatus(iocp_.handle,
+ 0, overlapped_contains_result, op))
+ {
+ // Out of resources. Put on completed queue instead.
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ completed_ops_.push(op);
+ }
+ }
 
- // Operation has been successfully posted.
- ptr.release();
+ // Request invocation of the given operation and return immediately. Assumes
+ // that work_started() was previously called for the operations.
+ void post_deferred_completions(op_queue<operation>& ops)
+ {
+ while (operation* op = ops.front())
+ {
+ ops.pop();
+
+ // Flag the operation as ready.
+ op->ready_ = 1;
+
+ // Enqueue the operation on the I/O completion port.
+ if (!::PostQueuedCompletionStatus(iocp_.handle,
+ 0, overlapped_contains_result, op))
+ {
+ // Out of resources. Put on completed queue instead.
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ completed_ops_.push(op);
+ completed_ops_.push(ops);
+ }
+ }
   }
 
- // Request invocation of the given OVERLAPPED-derived operation.
- void post_completion(operation* op, DWORD op_last_error,
- DWORD bytes_transferred)
+ // Called after starting an overlapped I/O operation that did not complete
+ // immediately. The caller must have already called work_started() prior to
+ // starting the operation.
+ void on_pending(operation* op)
   {
+ if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+ {
+ // Enqueue the operation on the I/O completion port.
+ if (!::PostQueuedCompletionStatus(iocp_.handle,
+ 0, overlapped_contains_result, op))
+ {
+ // Out of resources. Put on completed queue instead.
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ completed_ops_.push(op);
+ }
+ }
+ }
+
+ // Called after starting an overlapped I/O operation that completed
+ // immediately. The caller must have already called work_started() prior to
+ // starting the operation.
+ void on_completion(operation* op,
+ DWORD last_error = 0, DWORD bytes_transferred = 0)
+ {
+ // Flag that the operation is ready for invocation.
+ op->ready_ = 1;
+
+ // Store results in the OVERLAPPED structure.
+ op->Internal = reinterpret_cast<ulong_ptr_t>(
+ &boost::asio::error::get_system_category());
+ op->Offset = last_error;
+ op->OffsetHigh = bytes_transferred;
+
     // Enqueue the operation on the I/O completion port.
     if (!::PostQueuedCompletionStatus(iocp_.handle,
- bytes_transferred, op_last_error, op))
+ 0, overlapped_contains_result, op))
     {
- DWORD last_error = ::GetLastError();
- boost::system::system_error e(
- boost::system::error_code(last_error,
- boost::asio::error::get_system_category()),
- "pqcs");
- boost::throw_exception(e);
+ // Out of resources. Put on completed queue instead.
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ completed_ops_.push(op);
+ }
+ }
+
+ // Called after starting an overlapped I/O operation that completed
+ // immediately. The caller must have already called work_started() prior to
+ // starting the operation.
+ void on_completion(operation* op,
+ const boost::system::error_code& ec, DWORD bytes_transferred = 0)
+ {
+ // Flag that the operation is ready for invocation.
+ op->ready_ = 1;
+
+ // Store results in the OVERLAPPED structure.
+ op->Internal = reinterpret_cast<ulong_ptr_t>(&ec.category());
+ op->Offset = ec.value();
+ op->OffsetHigh = bytes_transferred;
+
+ // Enqueue the operation on the I/O completion port.
+ if (!::PostQueuedCompletionStatus(iocp_.handle,
+ 0, overlapped_contains_result, op))
+ {
+ // Out of resources. Put on completed queue instead.
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ completed_ops_.push(op);
     }
   }
 
@@ -367,7 +390,7 @@
   void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
- timer_queues_.push_back(&timer_queue);
+ timer_queues_.insert(&timer_queue);
   }
 
   // Remove a timer queue from the service.
@@ -375,36 +398,28 @@
   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
   {
     boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- if (timer_queues_[i] == &timer_queue)
- {
- timer_queues_.erase(timer_queues_.begin() + i);
- return;
- }
- }
+ timer_queues_.erase(&timer_queue);
   }
 
- // Schedule a timer in the given timer queue to expire at the specified
- // absolute time. The handler object will be invoked when the timer expires.
- template <typename Time_Traits, typename Handler>
+ // 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, Handler handler, void* token)
+ const typename Time_Traits::time_type& time, timer_op* op, void* token)
   {
     // If the service has been shut down we silently discard the timer.
     if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
       return;
 
     boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
- if (timer_queue.enqueue_timer(time, handler, token))
+ bool interrupt = timer_queue.enqueue_timer(time, op, token);
+ work_started();
+ if (interrupt && !timer_interrupt_issued_)
     {
- if (!timer_interrupt_issued_)
- {
- timer_interrupt_issued_ = true;
- lock.unlock();
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, steal_timer_dispatching, 0);
- }
+ timer_interrupt_issued_ = true;
+ lock.unlock();
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, steal_timer_dispatching, 0);
     }
   }
 
@@ -418,7 +433,9 @@
       return 0;
 
     boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
- std::size_t n = timer_queue.cancel_timer(token);
+ op_queue<operation> ops;
+ std::size_t n = timer_queue.cancel_timer(token, ops);
+ post_deferred_completions(ops);
     if (n > 0 && !timer_interrupt_issued_)
     {
       timer_interrupt_issued_ = true;
@@ -430,6 +447,14 @@
   }
 
 private:
+#if defined(WINVER) && (WINVER < 0x0500)
+ typedef DWORD dword_ptr_t;
+ typedef ULONG ulong_ptr_t;
+#else // defined(WINVER) && (WINVER < 0x0500)
+ typedef DWORD_PTR dword_ptr_t;
+ typedef ULONG_PTR ulong_ptr_t;
+#endif // defined(WINVER) && (WINVER < 0x0500)
+
   // Dequeues at most one operation from the I/O completion port, and then
   // executes it. Returns the number of operations that were dequeued (i.e.
   // either 0 or 1).
@@ -454,11 +479,7 @@
 
       // Get the next operation from the queue.
       DWORD bytes_transferred = 0;
-#if defined(WINVER) && (WINVER < 0x0500)
- DWORD completion_key = 0;
-#else
- DWORD_PTR completion_key = 0;
-#endif
+ dword_ptr_t completion_key = 0;
       LPOVERLAPPED overlapped = 0;
       ::SetLastError(0);
       BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
@@ -468,32 +489,11 @@
       // Dispatch any pending timers.
       if (dispatching_timers)
       {
- try
- {
- boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
- if (!timer_queues_.empty())
- {
- timer_queues_copy_ = timer_queues_;
- for (std::size_t i = 0; i < timer_queues_copy_.size(); ++i)
- {
- timer_queues_copy_[i]->dispatch_timers();
- timer_queues_copy_[i]->dispatch_cancellations();
- timer_queues_copy_[i]->complete_timers();
- }
- }
- }
- catch (...)
- {
- // Transfer responsibility for dispatching timers to another thread.
- if (::InterlockedCompareExchange(&timer_thread_,
- 0, this_thread_id) == this_thread_id)
- {
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, transfer_timer_dispatching, 0);
- }
-
- throw;
- }
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ op_queue<operation> ops;
+ ops.push(completed_ops_);
+ timer_queues_.get_ready_timers(ops);
+ post_deferred_completions(ops);
       }
 
       if (!ok && overlapped == 0)
@@ -522,11 +522,9 @@
       }
       else if (overlapped)
       {
- // We may have been passed a last_error value in the completion_key.
- if (last_error == 0)
- {
- last_error = completion_key;
- }
+ operation* op = static_cast<operation*>(overlapped);
+ boost::system::error_code result_ec(last_error,
+ boost::asio::error::get_system_category());
 
         // Transfer responsibility for dispatching timers to another thread.
         if (dispatching_timers && ::InterlockedCompareExchange(
@@ -536,14 +534,35 @@
               0, transfer_timer_dispatching, 0);
         }
 
- // Ensure that the io_service does not exit due to running out of work
- // while we make the upcall.
- auto_work work(*this);
+ // We may have been passed the last_error and bytes_transferred in the
+ // OVERLAPPED structure itself.
+ if (completion_key == overlapped_contains_result)
+ {
+ result_ec = boost::system::error_code(static_cast<int>(op->Offset),
+ *reinterpret_cast<boost::system::error_category*>(op->Internal));
+ bytes_transferred = op->OffsetHigh;
+ }
 
- // Dispatch the operation.
- operation* op = static_cast<operation*>(overlapped);
- if (op->on_completion(last_error, bytes_transferred))
+ // Otherwise ensure any result has been saved into the OVERLAPPED
+ // structure.
+ else
         {
+ op->Internal = reinterpret_cast<ulong_ptr_t>(&result_ec.category());
+ op->Offset = result_ec.value();
+ op->OffsetHigh = bytes_transferred;
+ }
+
+ // Dispatch the operation only if ready. The operation may not be ready
+ // if the initiating function (e.g. a call to WSARecv) has not yet
+ // returned. This is because the initiating function still wants access
+ // to the operation's OVERLAPPED structure.
+ if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+ {
+ // Ensure the count of outstanding work is decremented on block exit.
+ work_finished_on_block_exit on_exit = { this };
+ (void)on_exit;
+
+ op->complete(*this, result_ec, bytes_transferred);
           ec = boost::system::error_code();
           return 1;
         }
@@ -588,126 +607,23 @@
     }
   }
 
- // Check if all timer queues are empty.
- bool all_timer_queues_are_empty() const
- {
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- if (!timer_queues_[i]->empty())
- return false;
- return true;
- }
-
   // Get the timeout value for the GetQueuedCompletionStatus call. The timeout
   // value is returned as a number of milliseconds. We will wait no longer than
   // 1000 milliseconds.
   DWORD get_timeout()
   {
- if (all_timer_queues_are_empty())
- return max_timeout;
-
- boost::posix_time::time_duration minimum_wait_duration
- = boost::posix_time::milliseconds(max_timeout);
-
- for (std::size_t i = 0; i < timer_queues_.size(); ++i)
- {
- boost::posix_time::time_duration wait_duration
- = timer_queues_[i]->wait_duration();
- if (wait_duration < minimum_wait_duration)
- minimum_wait_duration = wait_duration;
- }
-
- if (minimum_wait_duration > boost::posix_time::time_duration())
- {
- int milliseconds = minimum_wait_duration.total_milliseconds();
- return static_cast<DWORD>(milliseconds > 0 ? milliseconds : 1);
- }
- else
- {
- return 0;
- }
+ return timer_queues_.wait_duration_msec(max_timeout);
   }
 
- struct auto_work
+ // Helper class to call work_finished() on block exit.
+ struct work_finished_on_block_exit
   {
- auto_work(win_iocp_io_service& io_service)
- : io_service_(io_service)
+ ~work_finished_on_block_exit()
     {
- io_service_.work_started();
+ io_service_->work_finished();
     }
 
- ~auto_work()
- {
- io_service_.work_finished();
- }
-
- private:
- win_iocp_io_service& io_service_;
- };
-
- template <typename Handler>
- struct handler_operation
- : public operation
- {
- handler_operation(win_iocp_io_service& io_service,
- Handler handler)
- : operation(io_service, &handler_operation<Handler>::do_completion_impl,
- &handler_operation<Handler>::destroy_impl),
- io_service_(io_service),
- handler_(handler)
- {
- io_service_.work_started();
- }
-
- ~handler_operation()
- {
- io_service_.work_finished();
- }
-
- private:
- // Prevent copying and assignment.
- handler_operation(const handler_operation&);
- void operator=(const handler_operation&);
-
- static void do_completion_impl(operation* op, DWORD, size_t)
- {
- // Take ownership of the operation object.
- typedef handler_operation<Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef handler_operation<Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
-
- win_iocp_io_service& io_service_;
- Handler handler_;
+ win_iocp_io_service* io_service_;
   };
 
   // The IO completion port used for queueing operations.
@@ -721,10 +637,6 @@
   // The count of unfinished work.
   long outstanding_work_;
 
- // The count of unfinished operations.
- long outstanding_operations_;
- friend class operation;
-
   // Flag to indicate whether the event loop has been stopped.
   long stopped_;
 
@@ -742,7 +654,12 @@
 
     // Completion key value to indicate that responsibility for dispatching
     // timers should be stolen from another thread.
- steal_timer_dispatching = 2
+ steal_timer_dispatching = 2,
+
+ // Completion key value to indicate that an operation has posted with the
+ // original last_error and bytes_transferred values stored in the fields of
+ // the OVERLAPPED structure.
+ overlapped_contains_result = 3
   };
 
   // The thread that's currently in charge of dispatching timers.
@@ -755,12 +672,10 @@
   bool timer_interrupt_issued_;
 
   // The timer queues.
- std::vector<timer_queue_base*> timer_queues_;
+ timer_queue_set timer_queues_;
 
- // A copy of the timer queues, used when dispatching, cancelling and cleaning
- // up timers. The copy is stored as a class data member to avoid unnecessary
- // memory allocation.
- std::vector<timer_queue_base*> timer_queues_copy_;
+ // The operations that are ready to dispatch.
+ op_queue<operation> completed_ops_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/win_iocp_overlapped_ptr.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_overlapped_ptr.hpp (original)
+++ branches/release/boost/asio/detail/win_iocp_overlapped_ptr.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -21,8 +21,10 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
 #include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_operation.hpp>
 
 namespace boost {
 namespace asio {
@@ -35,7 +37,8 @@
 public:
   // Construct an empty win_iocp_overlapped_ptr.
   win_iocp_overlapped_ptr()
- : ptr_(0)
+ : ptr_(0),
+ iocp_service_(0)
   {
   }
 
@@ -43,7 +46,8 @@
   template <typename Handler>
   explicit win_iocp_overlapped_ptr(
       boost::asio::io_service& io_service, Handler handler)
- : ptr_(0)
+ : ptr_(0),
+ iocp_service_(0)
   {
     this->reset(io_service, handler);
   }
@@ -61,6 +65,8 @@
     {
       ptr_->destroy();
       ptr_ = 0;
+ iocp_service_->work_finished();
+ iocp_service_ = 0;
     }
   }
 
@@ -69,12 +75,14 @@
   template <typename Handler>
   void reset(boost::asio::io_service& io_service, Handler handler)
   {
- typedef overlapped_operation<Handler> value_type;
+ typedef overlapped_op<Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, io_service.impl_, handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+ io_service.impl_.work_started();
     reset();
     ptr_ = ptr.release();
+ iocp_service_ = &io_service.impl_;
   }
 
   // Get the contained OVERLAPPED object.
@@ -93,10 +101,11 @@
   OVERLAPPED* release()
   {
     if (ptr_)
- ptr_->on_pending();
+ iocp_service_->on_pending(ptr_);
 
     OVERLAPPED* tmp = ptr_;
     ptr_ = 0;
+ iocp_service_ = 0;
     return tmp;
   }
 
@@ -106,99 +115,54 @@
   {
     if (ptr_)
     {
- ptr_->ec_ = ec;
- ptr_->on_immediate_completion(0, static_cast<DWORD>(bytes_transferred));
+ iocp_service_->on_completion(ptr_, ec,
+ static_cast<DWORD>(bytes_transferred));
       ptr_ = 0;
+ iocp_service_ = 0;
     }
   }
 
 private:
- struct overlapped_operation_base
- : public win_iocp_io_service::operation
- {
- overlapped_operation_base(win_iocp_io_service& io_service,
- invoke_func_type invoke_func, destroy_func_type destroy_func)
- : win_iocp_io_service::operation(io_service, invoke_func, destroy_func),
- io_service_(io_service)
- {
- io_service_.work_started();
- }
-
- ~overlapped_operation_base()
- {
- io_service_.work_finished();
- }
-
- win_iocp_io_service& io_service_;
- boost::system::error_code ec_;
- };
-
   template <typename Handler>
- struct overlapped_operation
- : public overlapped_operation_base
+ struct overlapped_op : public win_iocp_operation
   {
- overlapped_operation(win_iocp_io_service& io_service,
- Handler handler)
- : overlapped_operation_base(io_service,
- &overlapped_operation<Handler>::do_completion_impl,
- &overlapped_operation<Handler>::destroy_impl),
+ overlapped_op(Handler handler)
+ : win_iocp_operation(&overlapped_op::do_complete),
         handler_(handler)
     {
     }
 
- private:
- // Prevent copying and assignment.
- overlapped_operation(const overlapped_operation&);
- void operator=(const overlapped_operation&);
-
- static void do_completion_impl(win_iocp_io_service::operation* op,
- DWORD last_error, size_t bytes_transferred)
- {
- // Take ownership of the operation object.
- typedef overlapped_operation<Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // Make a copy of the handler and error_code so that the memory can be
- // deallocated before the upcall is made.
- Handler handler(handler_op->handler_);
- boost::system::error_code ec(handler_op->ec_);
- if (last_error)
- ec = boost::system::error_code(last_error,
- boost::asio::error::get_system_category());
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(
- bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(win_iocp_io_service::operation* op)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef overlapped_operation<Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
+ overlapped_op* o(static_cast<overlapped_op*>(base));
+ typedef handler_alloc_traits<Handler, overlapped_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
+ private:
     Handler handler_;
   };
 
- overlapped_operation_base* ptr_;
+ win_iocp_operation* ptr_;
+ win_iocp_io_service* iocp_service_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/win_iocp_serial_port_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_serial_port_service.hpp (original)
+++ branches/release/boost/asio/detail/win_iocp_serial_port_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -37,7 +37,6 @@
 
 // Extend win_iocp_handle_service to provide serial port support.
 class win_iocp_serial_port_service
- : public boost::asio::detail::service_base<win_iocp_serial_port_service>
 {
 public:
   // The native type of a stream handle.
@@ -47,10 +46,7 @@
   typedef win_iocp_handle_service::implementation_type implementation_type;
 
   win_iocp_serial_port_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- win_iocp_serial_port_service>(io_service),
- handle_service_(
- boost::asio::use_service<win_iocp_handle_service>(io_service))
+ : handle_service_(io_service)
   {
   }
 
@@ -279,8 +275,8 @@
   }
 
 private:
- // The handle service used for initiating asynchronous operations.
- win_iocp_handle_service& handle_service_;
+ // The implementation used for initiating asynchronous operations.
+ win_iocp_handle_service handle_service_;
 };
 
 } // namespace detail

Modified: branches/release/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_socket_service.hpp (original)
+++ branches/release/boost/asio/detail/win_iocp_socket_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -28,15 +28,19 @@
 #include <boost/weak_ptr.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
-#include <boost/asio/buffer.hpp>
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/socket_base.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/mutex.hpp>
-#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/null_buffers_op.hpp>
+#include <boost/asio/detail/operation.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/socket_holder.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
@@ -48,7 +52,6 @@
 
 template <typename Protocol>
 class win_iocp_socket_service
- : public boost::asio::detail::service_base<win_iocp_socket_service<Protocol> >
 {
 public:
   // The protocol type.
@@ -57,9 +60,6 @@
   // The endpoint type.
   typedef typename Protocol::endpoint endpoint_type;
 
- // Base class for all operations.
- typedef win_iocp_io_service::operation operation;
-
   struct noop_deleter { void operator()(void*) {} };
   typedef boost::shared_ptr<void> shared_cancel_token_type;
   typedef boost::weak_ptr<void> weak_cancel_token_type;
@@ -114,9 +114,6 @@
     endpoint_type remote_endpoint_;
   };
 
- // The type of the reactor used for connect operations.
- typedef detail::select_reactor<true> reactor_type;
-
   // The implementation type of the socket.
   class implementation_type
   {
@@ -161,7 +158,7 @@
     protocol_type protocol_;
 
     // Per-descriptor data used by the reactor.
- reactor_type::per_descriptor_data reactor_data_;
+ reactor::per_descriptor_data reactor_data_;
 
 #if defined(BOOST_ASIO_ENABLE_CANCELIO)
     // The ID of the thread from which it is safe to cancel asynchronous
@@ -176,14 +173,10 @@
     implementation_type* prev_;
   };
 
- // The maximum number of buffers to support in a single operation.
- enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
-
   // Constructor.
   win_iocp_socket_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- win_iocp_socket_service<Protocol> >(io_service),
- iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+ : io_service_(io_service),
+ iocp_service_(use_service<win_iocp_io_service>(io_service)),
       reactor_(0),
       mutex_(),
       impl_list_(0)
@@ -304,11 +297,11 @@
       // Check if the reactor was created, in which case we need to close the
       // socket on the reactor as well to cancel any operations that might be
       // running there.
- reactor_type* reactor = static_cast<reactor_type*>(
+ reactor* r = static_cast<reactor*>(
             interlocked_compare_exchange_pointer(
               reinterpret_cast<void**>(&reactor_), 0, 0));
- if (reactor)
- reactor->close_descriptor(impl.socket_, impl.reactor_data_);
+ if (r)
+ r->close_descriptor(impl.socket_, impl.reactor_data_);
 
       if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
         return ec;
@@ -665,23 +658,11 @@
       return 0;
     }
 
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = const_cast<char*>(
- boost::asio::buffer_cast<const char*>(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
     // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
@@ -689,8 +670,8 @@
 
     // Send the data.
     DWORD bytes_transferred = 0;
- int result = ::WSASend(impl.socket_, bufs,
- i, &bytes_transferred, flags, 0, 0);
+ int result = ::WSASend(impl.socket_, bufs.buffers(),
+ bufs.count(), &bytes_transferred, flags, 0, 0);
     if (result != 0)
     {
       DWORD last_error = ::WSAGetLastError();
@@ -724,94 +705,63 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class send_operation
- : public operation
+ class send_op : public operation
   {
   public:
- send_operation(win_iocp_io_service& io_service,
- weak_cancel_token_type cancel_token,
+ send_op(weak_cancel_token_type cancel_token,
         const ConstBufferSequence& buffers, Handler handler)
- : operation(io_service,
- &send_operation<ConstBufferSequence, Handler>::do_completion_impl,
- &send_operation<ConstBufferSequence, Handler>::destroy_impl),
- work_(io_service.get_io_service()),
+ : operation(&send_op::do_complete),
         cancel_token_(cancel_token),
         buffers_(buffers),
         handler_(handler)
     {
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef send_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ send_op* o(static_cast<send_op*>(base));
+ typedef handler_alloc_traits<Handler, send_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename ConstBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename ConstBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::const_buffer buffer(*iter);
- boost::asio::buffer_cast<const char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Map non-portable errors to their portable counterparts.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- if (handler_op->cancel_token_.expired())
- ec = boost::asio::error::operation_aborted;
- else
- ec = boost::asio::error::connection_reset;
- }
- else if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = boost::asio::error::connection_refused;
- }
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost_asio_handler_invoke_helpers::invoke(
- detail::bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef send_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (o->cancel_token_.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
 
- // Free the memory associated with the handler.
- ptr.reset();
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
- boost::asio::io_service::work work_;
+ private:
     weak_cancel_token_type cancel_token_;
     ConstBufferSequence buffers_;
     Handler handler_;
@@ -823,127 +773,34 @@
   void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
       socket_base::message_flags flags, Handler handler)
   {
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
     // Allocate and construct an operation to wrap the handler.
- typedef send_operation<ConstBufferSequence, Handler> value_type;
+ typedef send_op<ConstBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_,
+ handler_ptr<alloc_traits> ptr(raw_ptr,
         impl.cancel_token_, buffers, handler);
 
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
-
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = const_cast<char*>(
- boost::asio::buffer_cast<const char*>(buffer));
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
- {
- ptr.get()->on_immediate_completion(0, 0);
- ptr.release();
- return;
- }
-
- // Send the data.
- DWORD bytes_transferred = 0;
- int result = ::WSASend(impl.socket_, bufs, i,
- &bytes_transferred, flags, ptr.get(), 0);
- DWORD last_error = ::WSAGetLastError();
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
- // Check if the operation completed immediately.
- if (result != 0 && last_error != WSA_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_send_op(impl, bufs.buffers(), bufs.count(), flags,
+ impl.protocol_.type() == SOCK_STREAM && bufs.all_empty(), ptr.get());
+ ptr.release();
   }
 
- template <typename Handler>
- class null_buffers_operation
- {
- public:
- null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
- : work_(io_service),
- handler_(handler)
- {
- }
-
- bool perform(boost::system::error_code&,
- std::size_t& bytes_transferred)
- {
- 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_;
- };
-
   // Start an asynchronous wait until data can be sent without blocking.
   template <typename Handler>
   void async_send(implementation_type& impl, const null_buffers&,
       socket_base::message_flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Check if the reactor was already obtained from the io_service.
- reactor_type* reactor = static_cast<reactor_type*>(
- interlocked_compare_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), 0, 0));
- if (!reactor)
- {
- reactor = &(boost::asio::use_service<reactor_type>(
- this->get_io_service()));
- interlocked_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), reactor);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- reactor->start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ start_reactor_op(impl, reactor::write_op, ptr.get());
+ ptr.release();
   }
 
   // Send a datagram to the specified endpoint. Returns the number of bytes
@@ -959,23 +816,14 @@
       return 0;
     }
 
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = const_cast<char*>(
- boost::asio::buffer_cast<const char*>(buffer));
- }
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
     // Send the data.
     DWORD bytes_transferred = 0;
- int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred,
- flags, destination.data(), static_cast<int>(destination.size()), 0, 0);
+ int result = ::WSASendTo(impl.socket_, bufs.buffers(), bufs.count(),
+ &bytes_transferred, flags, destination.data(),
+ static_cast<int>(destination.size()), 0, 0);
     if (result != 0)
     {
       DWORD last_error = ::WSAGetLastError();
@@ -1008,85 +856,57 @@
   }
 
   template <typename ConstBufferSequence, typename Handler>
- class send_to_operation
- : public operation
+ class send_to_op : public operation
   {
   public:
- send_to_operation(win_iocp_io_service& io_service,
+ send_to_op(weak_cancel_token_type cancel_token,
         const ConstBufferSequence& buffers, Handler handler)
- : operation(io_service,
- &send_to_operation<ConstBufferSequence, Handler>::do_completion_impl,
- &send_to_operation<ConstBufferSequence, Handler>::destroy_impl),
- work_(io_service.get_io_service()),
+ : operation(&send_to_op::do_complete),
+ cancel_token_(cancel_token),
         buffers_(buffers),
         handler_(handler)
     {
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef send_to_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ send_to_op* o(static_cast<send_to_op*>(base));
+ typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename ConstBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename ConstBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::const_buffer buffer(*iter);
- boost::asio::buffer_cast<const char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Map non-portable errors to their portable counterparts.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = boost::asio::error::connection_refused;
- }
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost_asio_handler_invoke_helpers::invoke(
- detail::bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef send_to_operation<ConstBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
 
- // Free the memory associated with the handler.
- ptr.reset();
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
- boost::asio::io_service::work work_;
+ private:
+ weak_cancel_token_type cancel_token_;
     ConstBufferSequence buffers_;
     Handler handler_;
   };
@@ -1098,57 +918,19 @@
       const ConstBufferSequence& buffers, const endpoint_type& destination,
       socket_base::message_flags flags, Handler handler)
   {
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
     // Allocate and construct an operation to wrap the handler.
- typedef send_to_operation<ConstBufferSequence, Handler> value_type;
+ typedef send_to_op<ConstBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
-
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
-
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename ConstBufferSequence::const_iterator iter = buffers.begin();
- typename ConstBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::const_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = const_cast<char*>(
- boost::asio::buffer_cast<const char*>(buffer));
- }
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ impl.cancel_token_, buffers, handler);
 
- // Send the data.
- DWORD bytes_transferred = 0;
- int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags,
- destination.data(), static_cast<int>(destination.size()), ptr.get(), 0);
- DWORD last_error = ::WSAGetLastError();
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
 
- // Check if the operation completed immediately.
- if (result != 0 && last_error != WSA_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_send_to_op(impl, bufs.buffers(),
+ bufs.count(), destination, flags, ptr.get());
+ ptr.release();
   }
 
   // Start an asynchronous wait until data can be sent without blocking.
@@ -1156,29 +938,14 @@
   void async_send_to(implementation_type& impl, const null_buffers&,
       socket_base::message_flags, const endpoint_type&, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Check if the reactor was already obtained from the io_service.
- reactor_type* reactor = static_cast<reactor_type*>(
- interlocked_compare_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), 0, 0));
- if (!reactor)
- {
- reactor = &(boost::asio::use_service<reactor_type>(
- this->get_io_service()));
- interlocked_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), reactor);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- reactor->start_write_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ start_reactor_op(impl, reactor::write_op, ptr.get());
+ ptr.release();
   }
 
   // Receive some data from the peer. Returns the number of bytes received.
@@ -1193,22 +960,11 @@
       return 0;
     }
 
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
     // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
     {
       ec = boost::system::error_code();
       return 0;
@@ -1217,8 +973,8 @@
     // Receive some data.
     DWORD bytes_transferred = 0;
     DWORD recv_flags = flags;
- int result = ::WSARecv(impl.socket_, bufs, i,
- &bytes_transferred, &recv_flags, 0, 0);
+ int result = ::WSARecv(impl.socket_, bufs.buffers(),
+ bufs.count(), &bytes_transferred, &recv_flags, 0, 0);
     if (result != 0)
     {
       DWORD last_error = ::WSAGetLastError();
@@ -1257,106 +1013,73 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class receive_operation
- : public operation
+ class receive_op : public operation
   {
   public:
- receive_operation(int protocol_type, win_iocp_io_service& io_service,
- weak_cancel_token_type cancel_token,
+ receive_op(int protocol_type, weak_cancel_token_type cancel_token,
         const MutableBufferSequence& buffers, Handler handler)
- : operation(io_service,
- &receive_operation<
- MutableBufferSequence, Handler>::do_completion_impl,
- &receive_operation<
- MutableBufferSequence, Handler>::destroy_impl),
+ : operation(&receive_op::do_complete),
         protocol_type_(protocol_type),
- work_(io_service.get_io_service()),
         cancel_token_(cancel_token),
         buffers_(buffers),
         handler_(handler)
     {
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef receive_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ receive_op* o(static_cast<receive_op*>(base));
+ typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename MutableBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename MutableBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::mutable_buffer buffer(*iter);
- boost::asio::buffer_cast<char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Map non-portable errors to their portable counterparts.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- if (handler_op->cancel_token_.expired())
- ec = boost::asio::error::operation_aborted;
- else
- ec = boost::asio::error::connection_reset;
- }
- else if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = boost::asio::error::connection_refused;
- }
-
- // Check for connection closed.
- else if (!ec && bytes_transferred == 0
- && handler_op->protocol_type_ == SOCK_STREAM
- && !boost::is_same<MutableBufferSequence, null_buffers>::value)
- {
- ec = boost::asio::error::eof;
- }
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost_asio_handler_invoke_helpers::invoke(
- detail::bind_handler(handler, ec, bytes_transferred), handler);
- }
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (o->cancel_token_.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
 
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef receive_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
+ // Check for connection closed.
+ else if (!ec && bytes_transferred == 0
+ && o->protocol_type_ == SOCK_STREAM
+ && !boost::is_same<MutableBufferSequence, null_buffers>::value)
+ {
+ ec = boost::asio::error::eof;
+ }
 
- // Free the memory associated with the handler.
- ptr.reset();
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
+ private:
     int protocol_type_;
- boost::asio::io_service::work work_;
     weak_cancel_token_type cancel_token_;
     MutableBufferSequence buffers_;
     Handler handler_;
@@ -1369,67 +1092,20 @@
       const MutableBufferSequence& buffers,
       socket_base::message_flags flags, Handler handler)
   {
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
     // Allocate and construct an operation to wrap the handler.
- typedef receive_operation<MutableBufferSequence, Handler> value_type;
+ typedef receive_op<MutableBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
     int protocol_type = impl.protocol_.type();
     handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
- iocp_service_, impl.cancel_token_, buffers, handler);
-
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
-
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- size_t total_buffer_size = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
- total_buffer_size += boost::asio::buffer_size(buffer);
- }
+ impl.cancel_token_, buffers, handler);
 
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
- {
- ptr.get()->on_immediate_completion(0, 0);
- ptr.release();
- return;
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
- // Receive some data.
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int result = ::WSARecv(impl.socket_, bufs, i,
- &bytes_transferred, &recv_flags, ptr.get(), 0);
- DWORD last_error = ::WSAGetLastError();
- if (result != 0 && last_error != WSA_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
+ protocol_type == SOCK_STREAM && bufs.all_empty(), ptr.get());
+ ptr.release();
   }
 
   // Wait until data can be received without blocking.
@@ -1437,75 +1113,36 @@
   void async_receive(implementation_type& impl, const null_buffers& buffers,
       socket_base::message_flags flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else if (impl.protocol_.type() == SOCK_STREAM)
+ if (impl.protocol_.type() == SOCK_STREAM)
     {
       // For stream sockets on Windows, we may issue a 0-byte overlapped
       // WSARecv to wait until there is data available on the socket.
 
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
       // Allocate and construct an operation to wrap the handler.
- typedef receive_operation<null_buffers, Handler> value_type;
+ typedef receive_op<null_buffers, Handler> value_type;
       typedef handler_alloc_traits<Handler, value_type> alloc_traits;
       raw_handler_ptr<alloc_traits> raw_ptr(handler);
       int protocol_type = impl.protocol_.type();
       handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
- iocp_service_, impl.cancel_token_, buffers, handler);
+ impl.cancel_token_, buffers, handler);
 
- // Issue a receive operation with an empty buffer.
       ::WSABUF buf = { 0, 0 };
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int result = ::WSARecv(impl.socket_, &buf, 1,
- &bytes_transferred, &recv_flags, ptr.get(), 0);
- DWORD last_error = ::WSAGetLastError();
- if (result != 0 && last_error != WSA_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_receive_op(impl, &buf, 1, flags, false, ptr.get());
+ ptr.release();
     }
     else
     {
- // Check if the reactor was already obtained from the io_service.
- reactor_type* reactor = static_cast<reactor_type*>(
- interlocked_compare_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), 0, 0));
- if (!reactor)
- {
- reactor = &(boost::asio::use_service<reactor_type>(
- this->get_io_service()));
- interlocked_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), reactor);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- if (flags & socket_base::message_out_of_band)
- {
- reactor->start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler));
- }
- else
- {
- reactor->start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
+ start_reactor_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get());
+ ptr.release();
     }
   }
 
@@ -1523,24 +1160,16 @@
       return 0;
     }
 
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
     // Receive some data.
     DWORD bytes_transferred = 0;
     DWORD recv_flags = flags;
     int endpoint_size = static_cast<int>(sender_endpoint.capacity());
- int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
- &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
+ int result = ::WSARecvFrom(impl.socket_, bufs.buffers(),
+ bufs.count(), &bytes_transferred, &recv_flags,
+ sender_endpoint.data(), &endpoint_size, 0, 0);
     if (result != 0)
     {
       DWORD last_error = ::WSAGetLastError();
@@ -1583,22 +1212,15 @@
   }
 
   template <typename MutableBufferSequence, typename Handler>
- class receive_from_operation
- : public operation
+ class receive_from_op : public operation
   {
   public:
- receive_from_operation(int protocol_type, win_iocp_io_service& io_service,
- endpoint_type& endpoint, const MutableBufferSequence& buffers,
- Handler handler)
- : operation(io_service,
- &receive_from_operation<
- MutableBufferSequence, Handler>::do_completion_impl,
- &receive_from_operation<
- MutableBufferSequence, Handler>::destroy_impl),
+ receive_from_op(int protocol_type, endpoint_type& endpoint,
+ const MutableBufferSequence& buffers, Handler handler)
+ : operation(&receive_from_op::do_complete),
         protocol_type_(protocol_type),
         endpoint_(endpoint),
         endpoint_size_(static_cast<int>(endpoint.capacity())),
- work_(io_service.get_io_service()),
         buffers_(buffers),
         handler_(handler)
     {
@@ -1609,83 +1231,51 @@
       return endpoint_size_;
     }
 
- private:
- static void do_completion_impl(operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
     {
       // Take ownership of the operation object.
- typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ receive_from_op* o(static_cast<receive_from_op*>(base));
+ typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
+ // Make the upcall if required.
+ if (owner)
+ {
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- typename MutableBufferSequence::const_iterator iter
- = handler_op->buffers_.begin();
- typename MutableBufferSequence::const_iterator end
- = handler_op->buffers_.end();
- while (iter != end)
- {
- boost::asio::mutable_buffer buffer(*iter);
- boost::asio::buffer_cast<char*>(buffer);
- ++iter;
- }
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
 #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
 
- // Map non-portable errors to their portable counterparts.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = boost::asio::error::connection_refused;
- }
-
- // Check for connection closed.
- if (!ec && bytes_transferred == 0
- && handler_op->protocol_type_ == SOCK_STREAM)
- {
- ec = boost::asio::error::eof;
- }
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
 
- // Record the size of the endpoint returned by the operation.
- handler_op->endpoint_.resize(handler_op->endpoint_size_);
+ // Record the size of the endpoint returned by the operation.
+ o->endpoint_.resize(o->endpoint_size_);
 
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost_asio_handler_invoke_helpers::invoke(
- detail::bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
- }
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
+ }
 
+ private:
     int protocol_type_;
     endpoint_type& endpoint_;
     int endpoint_size_;
- boost::asio::io_service::work work_;
+ weak_cancel_token_type cancel_token_;
     MutableBufferSequence buffers_;
     Handler handler_;
   };
@@ -1698,58 +1288,20 @@
       const MutableBufferSequence& buffers, endpoint_type& sender_endp,
       socket_base::message_flags flags, Handler handler)
   {
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
     // Allocate and construct an operation to wrap the handler.
- typedef receive_from_operation<MutableBufferSequence, Handler> value_type;
+ typedef receive_from_op<MutableBufferSequence, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
     int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
- iocp_service_, sender_endp, buffers, handler);
-
- if (!is_open(impl))
- {
- ptr.get()->on_immediate_completion(WSAEBADF, 0);
- ptr.release();
- return;
- }
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ protocol_type, sender_endp, buffers, handler);
 
- // Copy buffers into WSABUF array.
- ::WSABUF bufs[max_buffers];
- typename MutableBufferSequence::const_iterator iter = buffers.begin();
- typename MutableBufferSequence::const_iterator end = buffers.end();
- DWORD i = 0;
- for (; iter != end && i < max_buffers; ++iter, ++i)
- {
- boost::asio::mutable_buffer buffer(*iter);
- bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
- bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
- }
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
 
- // Receive some data.
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
- &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(),
- ptr.get(), 0);
- DWORD last_error = ::WSAGetLastError();
- if (result != 0 && last_error != WSA_IO_PENDING)
- {
- ptr.get()->on_immediate_completion(last_error, bytes_transferred);
- ptr.release();
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ start_receive_from_op(impl, bufs.buffers(), bufs.count(),
+ sender_endp, flags, &ptr.get()->endpoint_size(), ptr.get());
+ ptr.release();
   }
 
   // Wait until data can be received without blocking.
@@ -1758,40 +1310,20 @@
       const null_buffers&, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, Handler handler)
   {
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor, 0));
- }
- else
- {
- // Check if the reactor was already obtained from the io_service.
- reactor_type* reactor = static_cast<reactor_type*>(
- interlocked_compare_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), 0, 0));
- if (!reactor)
- {
- reactor = &(boost::asio::use_service<reactor_type>(
- this->get_io_service()));
- interlocked_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), reactor);
- }
+ // Allocate and construct an operation to wrap the handler.
+ typedef null_buffers_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
 
- // Reset endpoint since it can be given no sensible value at this time.
- sender_endpoint = endpoint_type();
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
 
- if (flags & socket_base::message_out_of_band)
- {
- reactor->start_except_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler));
- }
- else
- {
- reactor->start_read_op(impl.socket_, impl.reactor_data_,
- null_buffers_operation<Handler>(this->get_io_service(), handler),
- false);
- }
- }
+ start_reactor_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ ptr.get());
+ ptr.release();
   }
 
   // Accept a new connection.
@@ -1852,32 +1384,27 @@
   }
 
   template <typename Socket, typename Handler>
- class accept_operation
- : public operation
+ class accept_op : public operation
   {
   public:
- accept_operation(win_iocp_io_service& io_service,
- socket_type socket, socket_type new_socket, Socket& peer,
- const protocol_type& protocol, endpoint_type* peer_endpoint,
- bool enable_connection_aborted, Handler handler)
- : operation(io_service,
- &accept_operation<Socket, Handler>::do_completion_impl,
- &accept_operation<Socket, Handler>::destroy_impl),
- io_service_(io_service),
+ accept_op(win_iocp_io_service& iocp_service, socket_type socket,
+ Socket& peer, const protocol_type& protocol,
+ endpoint_type* peer_endpoint, bool enable_connection_aborted,
+ Handler handler)
+ : operation(&accept_op::do_complete),
+ iocp_service_(iocp_service),
         socket_(socket),
- new_socket_(new_socket),
         peer_(peer),
         protocol_(protocol),
         peer_endpoint_(peer_endpoint),
- work_(io_service.get_io_service()),
         enable_connection_aborted_(enable_connection_aborted),
         handler_(handler)
     {
     }
 
- socket_type new_socket()
+ socket_holder& new_socket()
     {
- return new_socket_.get();
+ return new_socket_;
     }
 
     void* output_buffer()
@@ -1890,166 +1417,145 @@
       return sizeof(sockaddr_storage_type) + 16;
     }
 
- private:
- static void do_completion_impl(operation* op, DWORD last_error, size_t)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t /*bytes_transferred*/)
     {
- // Take ownership of the operation object.
- typedef accept_operation<Socket, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+ // Take ownership of the handler object.
+ accept_op* o(static_cast<accept_op*>(base));
+ typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
 
- // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
- if (last_error == ERROR_NETNAME_DELETED)
+ // Make the upcall if required.
+ if (owner)
       {
- last_error = WSAECONNABORTED;
- }
+ // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ ec = boost::asio::error::connection_aborted;
+ }
 
- // Restart the accept operation if we got the connection_aborted error
- // and the enable_connection_aborted socket option is not set.
- if (last_error == WSAECONNABORTED
- && !ptr.get()->enable_connection_aborted_)
- {
- // Reset OVERLAPPED structure.
- ptr.get()->reset();
-
- // Create a new socket for the next connection, since the AcceptEx call
- // fails with WSAEINVAL if we try to reuse the same socket.
- boost::system::error_code ec;
- ptr.get()->new_socket_.reset();
- ptr.get()->new_socket_.reset(socket_ops::socket(
- ptr.get()->protocol_.family(), ptr.get()->protocol_.type(),
- ptr.get()->protocol_.protocol(), ec));
- if (ptr.get()->new_socket() != invalid_socket)
+ // Restart the accept operation if we got the connection_aborted error
+ // and the enable_connection_aborted socket option is not set.
+ if (ec == boost::asio::error::connection_aborted
+ && !o->enable_connection_aborted_)
         {
- // Accept a connection.
- DWORD bytes_read = 0;
- BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(),
- ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
- ptr.get()->address_length(), &bytes_read, ptr.get());
- last_error = ::WSAGetLastError();
+ // Reset OVERLAPPED structure.
+ o->reset();
 
- // Check if the operation completed immediately.
- if (!result && last_error != WSA_IO_PENDING)
+ // Create a new socket for the next connection, since the AcceptEx
+ // call fails with WSAEINVAL if we try to reuse the same socket.
+ o->new_socket_.reset();
+ o->new_socket_.reset(socket_ops::socket(o->protocol_.family(),
+ o->protocol_.type(), o->protocol_.protocol(), ec));
+ if (o->new_socket_.get() != invalid_socket)
           {
- if (last_error == ERROR_NETNAME_DELETED
- || last_error == WSAECONNABORTED)
+ // Accept a connection.
+ DWORD bytes_read = 0;
+ BOOL result = ::AcceptEx(o->socket_, o->new_socket_.get(),
+ o->output_buffer(), 0, o->address_length(),
+ o->address_length(), &bytes_read, o);
+ DWORD last_error = ::WSAGetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+
+ // Check if the operation completed immediately.
+ if (!result && last_error != WSA_IO_PENDING)
             {
- // Post this handler so that operation will be restarted again.
- ptr.get()->on_immediate_completion(last_error, 0);
- ptr.release();
- return;
+ if (last_error == ERROR_NETNAME_DELETED
+ || last_error == WSAECONNABORTED)
+ {
+ // Post this handler so that operation will be restarted again.
+ o->iocp_service_.work_started();
+ o->iocp_service_.on_completion(o, ec);
+ ptr.release();
+ return;
+ }
+ else
+ {
+ // Operation already complete. Continue with rest of this
+ // handler.
+ }
             }
             else
             {
- // Operation already complete. Continue with rest of this handler.
+ // Asynchronous operation has been successfully restarted.
+ o->iocp_service_.work_started();
+ o->iocp_service_.on_pending(o);
+ ptr.release();
+ return;
             }
           }
+ }
+
+ // Get the address of the peer.
+ endpoint_type peer_endpoint;
+ if (!ec)
+ {
+ LPSOCKADDR local_addr = 0;
+ int local_addr_length = 0;
+ LPSOCKADDR remote_addr = 0;
+ int remote_addr_length = 0;
+ GetAcceptExSockaddrs(o->output_buffer(), 0, o->address_length(),
+ o->address_length(), &local_addr, &local_addr_length,
+ &remote_addr, &remote_addr_length);
+ if (static_cast<std::size_t>(remote_addr_length)
+ > peer_endpoint.capacity())
+ {
+ ec = boost::asio::error::invalid_argument;
+ }
           else
           {
- // Asynchronous operation has been successfully restarted.
- ptr.get()->on_pending();
- ptr.release();
- return;
+ using namespace std; // For memcpy.
+ memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
+ peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
           }
         }
- }
 
- // Get the address of the peer.
- endpoint_type peer_endpoint;
- if (last_error == 0)
- {
- LPSOCKADDR local_addr = 0;
- int local_addr_length = 0;
- LPSOCKADDR remote_addr = 0;
- int remote_addr_length = 0;
- GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
- handler_op->address_length(), handler_op->address_length(),
- &local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
- if (static_cast<std::size_t>(remote_addr_length)
- > peer_endpoint.capacity())
+ // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
+ // and getpeername will work on the accepted socket.
+ if (!ec)
         {
- last_error = WSAEINVAL;
+ SOCKET update_ctx_param = o->socket_;
+ socket_ops::setsockopt(o->new_socket_.get(),
+ SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ &update_ctx_param, sizeof(SOCKET), ec);
         }
- else
- {
- using namespace std; // For memcpy.
- memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
- peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
- }
- }
 
- // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
- // and getpeername will work on the accepted socket.
- if (last_error == 0)
- {
- SOCKET update_ctx_param = handler_op->socket_;
- boost::system::error_code ec;
- if (socket_ops::setsockopt(handler_op->new_socket_.get(),
- SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
- &update_ctx_param, sizeof(SOCKET), ec) != 0)
+ // If the socket was successfully accepted, transfer ownership of the
+ // socket to the peer object.
+ if (!ec)
         {
- last_error = ec.value();
+ o->peer_.assign(o->protocol_,
+ native_type(o->new_socket_.get(), peer_endpoint), ec);
+ if (!ec)
+ o->new_socket_.release();
         }
- }
 
- // If the socket was successfully accepted, transfer ownership of the
- // socket to the peer object.
- if (last_error == 0)
- {
- boost::system::error_code ec;
- handler_op->peer_.assign(handler_op->protocol_,
- native_type(handler_op->new_socket_.get(), peer_endpoint), ec);
- if (ec)
- last_error = ec.value();
- else
- handler_op->new_socket_.release();
+ // Pass endpoint back to caller.
+ if (o->peer_endpoint_)
+ *o->peer_endpoint_ = peer_endpoint;
+
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder1<Handler, boost::system::error_code>
+ handler(o->handler_, ec);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
       }
-
- // Pass endpoint back to caller.
- if (handler_op->peer_endpoint_)
- *handler_op->peer_endpoint_ = peer_endpoint;
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made.
- Handler handler(handler_op->handler_);
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Call the handler.
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- boost_asio_handler_invoke_helpers::invoke(
- detail::bind_handler(handler, ec), handler);
- }
-
- static void destroy_impl(operation* op)
- {
- // Take ownership of the operation object.
- typedef accept_operation<Socket, Handler> op_type;
- op_type* handler_op(static_cast<op_type*>(op));
- typedef handler_alloc_traits<Handler, op_type> alloc_traits;
- handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
-
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(handler_op->handler_);
- (void)handler;
-
- // Free the memory associated with the handler.
- ptr.reset();
     }
 
- win_iocp_io_service& io_service_;
+ private:
+ win_iocp_io_service& iocp_service_;
     socket_type socket_;
     socket_holder new_socket_;
     Socket& peer_;
     protocol_type protocol_;
     endpoint_type* peer_endpoint_;
- boost::asio::io_service::work work_;
     unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
     bool enable_connection_aborted_;
     Handler handler_;
@@ -2061,86 +1567,18 @@
   void async_accept(implementation_type& impl, Socket& peer,
       endpoint_type* peer_endpoint, Handler handler)
   {
- // Check whether acceptor has been initialised.
- if (!is_open(impl))
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor));
- return;
- }
-
- // Check that peer socket has not already been opened.
- if (peer.is_open())
- {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::already_open));
- return;
- }
-
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
-
- // Create a new socket for the connection.
- boost::system::error_code ec;
- socket_holder sock(socket_ops::socket(impl.protocol_.family(),
- impl.protocol_.type(), impl.protocol_.protocol(), ec));
- if (sock.get() == invalid_socket)
- {
- this->get_io_service().post(bind_handler(handler, ec));
- return;
- }
-
     // Allocate and construct an operation to wrap the handler.
- typedef accept_operation<Socket, Handler> value_type;
+ typedef accept_op<Socket, Handler> value_type;
     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
     raw_handler_ptr<alloc_traits> raw_ptr(handler);
- socket_type new_socket = sock.get();
     bool enable_connection_aborted =
       (impl.flags_ & implementation_type::enable_connection_aborted);
- handler_ptr<alloc_traits> ptr(raw_ptr,
- iocp_service_, impl.socket_, new_socket, peer, impl.protocol_,
- peer_endpoint, enable_connection_aborted, handler);
- sock.release();
-
- // Accept a connection.
- DWORD bytes_read = 0;
- BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(),
- ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
- ptr.get()->address_length(), &bytes_read, ptr.get());
- DWORD last_error = ::WSAGetLastError();
-
- // Check if the operation completed immediately.
- if (!result && last_error != WSA_IO_PENDING)
- {
- if (!enable_connection_aborted
- && (last_error == ERROR_NETNAME_DELETED
- || last_error == WSAECONNABORTED))
- {
- // Post handler so that operation will be restarted again. We do not
- // perform the AcceptEx again here to avoid the possibility of starving
- // other handlers.
- ptr.get()->on_immediate_completion(last_error, 0);
- ptr.release();
- }
- else
- {
- boost::asio::io_service::work work(this->get_io_service());
- ptr.reset();
- boost::system::error_code ec(last_error,
- boost::asio::error::get_system_category());
- iocp_service_.post(bind_handler(handler, ec));
- }
- }
- else
- {
- ptr.get()->on_pending();
- ptr.release();
- }
+ handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, impl.socket_, peer,
+ impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
+
+ start_accept_op(impl, peer.is_open(), ptr.get()->new_socket(),
+ ptr.get()->output_buffer(), ptr.get()->address_length(), ptr.get());
+ ptr.release();
   }
 
   // Connect the socket to the specified endpoint.
@@ -2159,67 +1597,76 @@
     return ec;
   }
 
- template <typename Handler>
- class connect_operation
+ class connect_op_base : public reactor_op
   {
   public:
- 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),
- io_service_(io_service),
- work_(io_service),
- handler_(handler)
+ connect_op_base(socket_type socket, func_type complete_func)
+ : reactor_op(&connect_op_base::do_perform, complete_func),
+ socket_(socket)
     {
     }
 
- bool perform(boost::system::error_code& ec,
- std::size_t& bytes_transferred)
+ static bool do_perform(reactor_op* base)
     {
- bytes_transferred = 0;
-
- // Check whether the operation was successful.
- if (ec)
- return true;
+ connect_op_base* o(static_cast<connect_op_base*>(base));
 
       // Get the error code from the connect operation.
       int connect_error = 0;
       size_t connect_error_len = sizeof(connect_error);
- if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
- &connect_error, &connect_error_len, ec) == socket_error_retval)
+ if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
         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,
+ o->ec_ = boost::system::error_code(connect_error,
             boost::asio::error::get_system_category());
- return true;
       }
 
- // Revert socket to blocking mode unless the user requested otherwise.
- if (!user_set_non_blocking_)
- {
- ioctl_arg_type non_blocking = 0;
- if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec))
- return true;
- }
-
- // Post the result of the successful connection operation.
- ec = boost::system::error_code();
       return true;
     }
 
- void complete(const boost::system::error_code& ec, std::size_t)
+ private:
+ socket_type socket_;
+ };
+
+ template <typename Handler>
+ class connect_op : public connect_op_base
+ {
+ public:
+ connect_op(socket_type socket, Handler handler)
+ : connect_op_base(socket, &connect_op::do_complete),
+ handler_(handler)
     {
- io_service_.post(bind_handler(handler_, ec));
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ connect_op* o(static_cast<connect_op*>(base));
+ typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, a sub-object of the handler may be the true owner of the
+ // memory associated with the handler. Consequently, a local copy of
+ // the handler is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ detail::binder1<Handler, boost::system::error_code>
+ handler(o->handler_, o->ec_);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
     }
 
   private:
- socket_type socket_;
- bool user_set_non_blocking_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
     Handler handler_;
   };
 
@@ -2228,86 +1675,216 @@
   void async_connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, Handler handler)
   {
- if (!is_open(impl))
+ // Allocate and construct an operation to wrap the handler.
+ typedef connect_op<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, handler);
+
+ start_connect_op(impl, ptr.get(), peer_endpoint);
+ ptr.release();
+ }
+
+private:
+ // Helper function to start an asynchronous send operation.
+ void start_send_op(implementation_type& impl, WSABUF* buffers,
+ std::size_t buffer_count, socket_base::message_flags flags,
+ bool noop, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
+
+ if (noop)
+ iocp_service_.on_completion(op);
+ else if (!is_open(impl))
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ else
     {
- this->get_io_service().post(bind_handler(handler,
- boost::asio::error::bad_descriptor));
- return;
+ DWORD bytes_transferred = 0;
+ int result = ::WSASend(impl.socket_, buffers,
+ buffer_count, &bytes_transferred, flags, op, 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ else
+ iocp_service_.on_pending(op);
     }
+ }
 
-#if defined(BOOST_ASIO_ENABLE_CANCELIO)
- // Update the ID of the thread from which cancellation is safe.
- if (impl.safe_cancellation_thread_id_ == 0)
- impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
- else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
- impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Helper function to start an asynchronous send_to operation.
+ void start_send_to_op(implementation_type& impl, WSABUF* buffers,
+ std::size_t buffer_count, const endpoint_type& destination,
+ socket_base::message_flags flags, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
 
- // Check if the reactor was already obtained from the io_service.
- reactor_type* reactor = static_cast<reactor_type*>(
- interlocked_compare_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), 0, 0));
- if (!reactor)
+ if (!is_open(impl))
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ else
     {
- reactor = &(boost::asio::use_service<reactor_type>(
- this->get_io_service()));
- interlocked_exchange_pointer(
- reinterpret_cast<void**>(&reactor_), reactor);
+ DWORD bytes_transferred = 0;
+ int result = ::WSASendTo(impl.socket_, buffers, buffer_count,
+ &bytes_transferred, flags, destination.data(),
+ static_cast<int>(destination.size()), op, 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ else
+ iocp_service_.on_pending(op);
     }
+ }
+
+ // Helper function to start an asynchronous receive operation.
+ void start_receive_op(implementation_type& impl, WSABUF* buffers,
+ std::size_t buffer_count, socket_base::message_flags flags,
+ bool noop, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
 
- // Mark the socket as non-blocking so that the connection will take place
- // asynchronously.
- ioctl_arg_type non_blocking = 1;
- boost::system::error_code ec;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ if (noop)
+ iocp_service_.on_completion(op);
+ else if (!is_open(impl))
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ else
     {
- this->get_io_service().post(bind_handler(handler, ec));
- return;
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecv(impl.socket_, buffers, buffer_count,
+ &bytes_transferred, &recv_flags, op, 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_NETNAME_DELETED)
+ last_error = WSAECONNRESET;
+ else if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ else
+ iocp_service_.on_pending(op);
     }
+ }
+
+ // Helper function to start an asynchronous receive_from operation.
+ void start_receive_from_op(implementation_type& impl, WSABUF* buffers,
+ std::size_t buffer_count, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, int* endpoint_size, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
 
- // Start the connect operation.
- if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
- peer_endpoint.size(), ec) == 0)
- {
- // Revert socket to blocking mode unless the user requested otherwise.
- if (!(impl.flags_ & implementation_type::user_set_non_blocking))
- {
- non_blocking = 0;
- socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec);
- }
-
- // The connect operation has finished successfully so we need to post the
- // handler immediately.
- this->get_io_service().post(bind_handler(handler, ec));
- }
- else if (ec == boost::asio::error::in_progress
- || ec == boost::asio::error::would_block)
- {
- // The connection is happening in the background, and we need to wait
- // until the socket becomes writeable.
- boost::shared_ptr<bool> completed(new bool(false));
- reactor->start_connect_op(impl.socket_, impl.reactor_data_,
- connect_operation<Handler>(
- impl.socket_,
- (impl.flags_ & implementation_type::user_set_non_blocking) != 0,
- this->get_io_service(), handler));
+ if (!is_open(impl))
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ else
+ {
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecvFrom(impl.socket_, buffers,
+ buffer_count, &bytes_transferred, &recv_flags,
+ sender_endpoint.data(), endpoint_size, op, 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ iocp_service_.on_completion(op, last_error, bytes_transferred);
+ else
+ iocp_service_.on_pending(op);
     }
+ }
+
+ // Helper function to start an asynchronous receive_from operation.
+ void start_accept_op(implementation_type& impl,
+ bool peer_is_open, socket_holder& new_socket,
+ void* output_buffer, DWORD address_length, operation* op)
+ {
+ update_cancellation_thread_id();
+ iocp_service_.work_started();
+
+ if (!is_open(impl))
+ iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
+ else if (peer_is_open)
+ iocp_service_.on_completion(op, boost::asio::error::already_open);
     else
     {
- // Revert socket to blocking mode unless the user requested otherwise.
- if (!(impl.flags_ & implementation_type::user_set_non_blocking))
+ boost::system::error_code ec;
+ new_socket.reset(socket_ops::socket(impl.protocol_.family(),
+ impl.protocol_.type(), impl.protocol_.protocol(), ec));
+ if (new_socket.get() == invalid_socket)
+ iocp_service_.on_completion(op, ec);
+ else
       {
- non_blocking = 0;
- boost::system::error_code ignored_ec;
- socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
+ DWORD bytes_read = 0;
+ BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,
+ 0, address_length, address_length, &bytes_read, op);
+ DWORD last_error = ::WSAGetLastError();
+ if (!result && last_error != WSA_IO_PENDING)
+ iocp_service_.on_completion(op, last_error);
+ else
+ iocp_service_.on_pending(op);
       }
+ }
+ }
+
+ // Start an asynchronous read or write operation using the the reactor.
+ void start_reactor_op(implementation_type& impl, int op_type, reactor_op* op)
+ {
+ reactor& r = get_reactor();
+ update_cancellation_thread_id();
 
- // The connect operation has failed, so post the handler immediately.
- this->get_io_service().post(bind_handler(handler, ec));
+ if (is_open(impl))
+ {
+ r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
+ return;
     }
+ else
+ op->ec_ = boost::asio::error::bad_descriptor;
+
+ iocp_service_.post_immediate_completion(op);
+ }
+
+ // Start the asynchronous connect operation using the reactor.
+ void start_connect_op(implementation_type& impl,
+ reactor_op* op, const endpoint_type& peer_endpoint)
+ {
+ reactor& r = get_reactor();
+ update_cancellation_thread_id();
+
+ if (is_open(impl))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (!socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
+ peer_endpoint.size(), op->ec_) != 0)
+ {
+ if (!op->ec_
+ && !(impl.flags_ & implementation_type::user_set_non_blocking))
+ {
+ non_blocking = 0;
+ socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_);
+ }
+
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ r.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, true);
+ return;
+ }
+ }
+ }
+ }
+ else
+ op->ec_ = boost::asio::error::bad_descriptor;
+
+ iocp_service_.post_immediate_completion(op);
   }
 
-private:
   // Helper function to close a socket when the associated object is being
   // destroyed.
   void close_for_destruction(implementation_type& impl)
@@ -2317,11 +1894,11 @@
       // Check if the reactor was created, in which case we need to close the
       // socket on the reactor as well to cancel any operations that might be
       // running there.
- reactor_type* reactor = static_cast<reactor_type*>(
+ reactor* r = static_cast<reactor*>(
             interlocked_compare_exchange_pointer(
               reinterpret_cast<void**>(&reactor_), 0, 0));
- if (reactor)
- reactor->close_descriptor(impl.socket_, impl.reactor_data_);
+ if (r)
+ r->close_descriptor(impl.socket_, impl.reactor_data_);
 
       // The socket destructor must not block. If the user has changed the
       // linger option to block in the foreground, we will change it back to the
@@ -2347,6 +1924,33 @@
     }
   }
 
+ // Update the ID of the thread from which cancellation is safe.
+ void update_cancellation_thread_id()
+ {
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ if (impl.safe_cancellation_thread_id_ == 0)
+ impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+ else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+ impl.safe_cancellation_thread_id_ = ~DWORD(0);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ }
+
+ // Helper function to get the reactor. If no reactor has been created yet, a
+ // new one is obtained from the io_service and a pointer to it is cached in
+ // this service.
+ reactor& get_reactor()
+ {
+ reactor* r = static_cast<reactor*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!r)
+ {
+ r = &(use_service<reactor>(io_service_));
+ interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
+ }
+ return *r;
+ }
+
   // Helper function to emulate InterlockedCompareExchangePointer functionality
   // for:
   // - very old Platform SDKs; and
@@ -2375,13 +1979,16 @@
 #endif
   }
 
+ // The io_service used to obtain the reactor, if required.
+ boost::asio::io_service& io_service_;
+
   // The IOCP service used for running asynchronous operations and dispatching
   // handlers.
   win_iocp_io_service& iocp_service_;
 
   // The reactor used for performing connect operations. This object is created
   // only if needed.
- reactor_type* reactor_;
+ reactor* reactor_;
 
   // Mutex to protect access to the linked list of implementations.
   boost::asio::detail::mutex mutex_;

Modified: branches/release/boost/asio/detail/win_mutex.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_mutex.hpp (original)
+++ branches/release/boost/asio/detail/win_mutex.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -66,15 +66,7 @@
   // Lock the mutex.
   void lock()
   {
- int error = do_lock();
- if (error != 0)
- {
- boost::system::system_error e(
- boost::system::error_code(error,
- boost::asio::error::get_system_category()),
- "mutex");
- boost::throw_exception(e);
- }
+ ::EnterCriticalSection(&crit_section_);
   }
 
   // Unlock the mutex.
@@ -92,12 +84,12 @@
 #if defined(__MINGW32__)
     // Not sure if MinGW supports structured exception handling, so for now
     // we'll just call the Windows API and hope.
- ::InitializeCriticalSection(&crit_section_);
+ ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
     return 0;
 #else
     __try
     {
- ::InitializeCriticalSection(&crit_section_);
+ ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
     }
     __except(GetExceptionCode() == STATUS_NO_MEMORY
         ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
@@ -109,34 +101,6 @@
 #endif
   }
 
- // Locking must be performed in a separate function to lock() since the
- // compiler does not support the use of structured exceptions and C++
- // exceptions in the same function.
- int do_lock()
- {
-#if defined(__MINGW32__)
- // Not sure if MinGW supports structured exception handling, so for now
- // we'll just call the Windows API and hope.
- ::EnterCriticalSection(&crit_section_);
- return 0;
-#else
- __try
- {
- ::EnterCriticalSection(&crit_section_);
- }
- __except(GetExceptionCode() == STATUS_INVALID_HANDLE
- || GetExceptionCode() == STATUS_NO_MEMORY
- ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- if (GetExceptionCode() == STATUS_NO_MEMORY)
- return ERROR_OUTOFMEMORY;
- return ERROR_INVALID_HANDLE;
- }
-
- return 0;
-#endif
- }
-
   ::CRITICAL_SECTION crit_section_;
 };
 

Modified: branches/release/boost/asio/impl/io_service.ipp
==============================================================================
--- branches/release/boost/asio/impl/io_service.ipp (original)
+++ branches/release/boost/asio/impl/io_service.ipp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -26,18 +26,9 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 # include <boost/asio/detail/win_iocp_io_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/task_io_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/task_io_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/task_io_service.hpp>
 #else
-# include <boost/asio/detail/select_reactor.hpp>
 # include <boost/asio/detail/task_io_service.hpp>
+# include <boost/asio/detail/reactor.hpp>
 #endif
 
 namespace boost {
@@ -176,7 +167,6 @@
 
 inline io_service::service::service(boost::asio::io_service& owner)
   : owner_(owner),
- type_info_(0),
     next_(0)
 {
 }

Modified: branches/release/boost/asio/impl/read.ipp
==============================================================================
--- branches/release/boost/asio/impl/read.ipp (original)
+++ branches/release/boost/asio/impl/read.ipp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -24,6 +24,7 @@
 #include <boost/asio/buffer.hpp>
 #include <boost/asio/completion_condition.hpp>
 #include <boost/asio/error.hpp>
+#include <boost/asio/detail/base_from_completion_cond.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
@@ -42,14 +43,14 @@
   boost::asio::detail::consuming_buffers<
     mutable_buffer, MutableBufferSequence> tmp(buffers);
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   while (tmp.begin() != tmp.end())
   {
     std::size_t bytes_transferred = s.read_some(tmp, ec);
     tmp.consume(bytes_transferred);
     total_transferred += bytes_transferred;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
           completion_condition(ec, total_transferred)));
   }
   return total_transferred;
@@ -130,51 +131,111 @@
 {
   template <typename AsyncReadStream, typename MutableBufferSequence,
       typename CompletionCondition, typename ReadHandler>
- class read_handler
+ class read_op
+ : detail::base_from_completion_cond<CompletionCondition>
   {
   public:
- typedef boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> buffers_type;
-
- read_handler(AsyncReadStream& stream, const buffers_type& buffers,
+ read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
         CompletionCondition completion_condition, ReadHandler handler)
- : stream_(stream),
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
         buffers_(buffers),
         total_transferred_(0),
- completion_condition_(completion_condition),
- handler_(handler)
+ handler_(handler),
+ start_(true)
     {
     }
 
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred)
     {
- total_transferred_ += bytes_transferred;
- buffers_.consume(bytes_transferred);
- buffers_.set_max_size(detail::adapt_completion_condition_result(
- completion_condition_(ec, total_transferred_)));
- if (buffers_.begin() == buffers_.end())
+ switch (start_)
       {
+ case true: start_ = false;
+ buffers_.prepare(this->check(ec, total_transferred_));
+ for (;;)
+ {
+ stream_.async_read_some(buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
         handler_(ec, total_transferred_);
       }
- else
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ bool start_;
+ };
+
+ template <typename AsyncReadStream,
+ typename CompletionCondition, typename ReadHandler>
+ class read_op<AsyncReadStream, boost::asio::mutable_buffers_1,
+ CompletionCondition, ReadHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_op(AsyncReadStream& stream,
+ const boost::asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler),
+ start_(true)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ std::size_t n = 0;
+ switch (start_)
       {
- stream_.async_read_some(buffers_, *this);
+ case true: start_ = false;
+ n = this->check(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_read_some(boost::asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check(ec, total_transferred_)) == 0
+ || total_transferred_ == boost::asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, total_transferred_);
       }
     }
 
   //private:
     AsyncReadStream& stream_;
- buffers_type buffers_;
+ boost::asio::mutable_buffer buffer_;
     std::size_t total_transferred_;
- CompletionCondition completion_condition_;
     ReadHandler handler_;
+ bool start_;
   };
 
   template <typename AsyncReadStream, typename MutableBufferSequence,
       typename CompletionCondition, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
- read_handler<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     return boost_asio_handler_alloc_helpers::allocate(
@@ -184,7 +245,7 @@
   template <typename AsyncReadStream, typename MutableBufferSequence,
       typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_handler<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     boost_asio_handler_alloc_helpers::deallocate(
@@ -195,7 +256,7 @@
       typename MutableBufferSequence, typename CompletionCondition,
       typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
- read_handler<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     boost_asio_handler_invoke_helpers::invoke(
@@ -208,24 +269,10 @@
 inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
     CompletionCondition completion_condition, ReadHandler handler)
 {
- boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> tmp(buffers);
-
- boost::system::error_code ec;
- std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- if (tmp.begin() == tmp.end())
- {
- s.get_io_service().post(detail::bind_handler(
- handler, ec, total_transferred));
- return;
- }
-
- s.async_read_some(tmp,
- detail::read_handler<AsyncReadStream, MutableBufferSequence,
- CompletionCondition, ReadHandler>(
- s, tmp, completion_condition, handler));
+ detail::read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>(
+ s, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0);
 }
 
 template <typename AsyncReadStream, typename MutableBufferSequence,
@@ -242,52 +289,64 @@
 {
   template <typename AsyncReadStream, typename Allocator,
       typename CompletionCondition, typename ReadHandler>
- class read_streambuf_handler
+ class read_streambuf_op
+ : detail::base_from_completion_cond<CompletionCondition>
   {
   public:
- read_streambuf_handler(AsyncReadStream& stream,
+ read_streambuf_op(AsyncReadStream& stream,
         basic_streambuf<Allocator>& streambuf,
         CompletionCondition completion_condition, ReadHandler handler)
- : stream_(stream),
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
         streambuf_(streambuf),
         total_transferred_(0),
- completion_condition_(completion_condition),
- handler_(handler)
+ handler_(handler),
+ start_(true)
     {
     }
 
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred)
     {
- total_transferred_ += bytes_transferred;
- streambuf_.commit(bytes_transferred);
- std::size_t max_size = detail::adapt_completion_condition_result(
- completion_condition_(ec, total_transferred_));
- std::size_t bytes_available = std::min<std::size_t>(512,
- std::min<std::size_t>(max_size,
- streambuf_.max_size() - streambuf_.size()));
- if (bytes_available == 0)
+ std::size_t max_size, bytes_available;
+ switch (start_)
       {
+ case true: start_ = false;
+ max_size = this->check(ec, total_transferred_);
+ bytes_available = std::min<std::size_t>(512,
+ std::min<std::size_t>(max_size,
+ streambuf_.max_size() - streambuf_.size()));
+ for (;;)
+ {
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ streambuf_.commit(bytes_transferred);
+ max_size = this->check(ec, total_transferred_);
+ bytes_available = std::min<std::size_t>(512,
+ std::min<std::size_t>(max_size,
+ streambuf_.max_size() - streambuf_.size()));
+ if ((!ec && bytes_transferred == 0) || bytes_available == 0)
+ break;
+ }
+
         handler_(ec, total_transferred_);
       }
- else
- {
- stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
- }
     }
 
   //private:
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
     std::size_t total_transferred_;
- CompletionCondition completion_condition_;
     ReadHandler handler_;
+ bool start_;
   };
 
   template <typename AsyncReadStream, typename Allocator,
       typename CompletionCondition, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
- read_streambuf_handler<AsyncReadStream, Allocator,
+ read_streambuf_op<AsyncReadStream, Allocator,
         CompletionCondition, ReadHandler>* this_handler)
   {
     return boost_asio_handler_alloc_helpers::allocate(
@@ -297,7 +356,7 @@
   template <typename AsyncReadStream, typename Allocator,
       typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_streambuf_handler<AsyncReadStream, Allocator,
+ read_streambuf_op<AsyncReadStream, Allocator,
         CompletionCondition, ReadHandler>* this_handler)
   {
     boost_asio_handler_alloc_helpers::deallocate(
@@ -307,7 +366,7 @@
   template <typename Function, typename AsyncReadStream,
       typename Allocator, typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
- read_streambuf_handler<AsyncReadStream, Allocator,
+ read_streambuf_op<AsyncReadStream, Allocator,
         CompletionCondition, ReadHandler>* this_handler)
   {
     boost_asio_handler_invoke_helpers::invoke(
@@ -321,23 +380,10 @@
     boost::asio::basic_streambuf<Allocator>& b,
     CompletionCondition completion_condition, ReadHandler handler)
 {
- boost::system::error_code ec;
- std::size_t total_transferred = 0;
- std::size_t max_size = detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred));
- std::size_t bytes_available = std::min<std::size_t>(512,
- std::min<std::size_t>(max_size, b.max_size() - b.size()));
- if (bytes_available == 0)
- {
- s.get_io_service().post(detail::bind_handler(
- handler, ec, total_transferred));
- return;
- }
-
- s.async_read_some(b.prepare(bytes_available),
- detail::read_streambuf_handler<AsyncReadStream, Allocator,
- CompletionCondition, ReadHandler>(
- s, b, completion_condition, handler));
+ detail::read_streambuf_op<AsyncReadStream,
+ Allocator, CompletionCondition, ReadHandler>(
+ s, b, completion_condition, handler)(
+ boost::system::error_code(), 0);
 }
 
 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>

Modified: branches/release/boost/asio/impl/read_at.ipp
==============================================================================
--- branches/release/boost/asio/impl/read_at.ipp (original)
+++ branches/release/boost/asio/impl/read_at.ipp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -43,7 +43,7 @@
   boost::asio::detail::consuming_buffers<
     mutable_buffer, MutableBufferSequence> tmp(buffers);
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   while (tmp.begin() != tmp.end())
   {
@@ -51,7 +51,7 @@
         offset + total_transferred, tmp, ec);
     tmp.consume(bytes_transferred);
     total_transferred += bytes_transferred;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
           completion_condition(ec, total_transferred)));
   }
   return total_transferred;
@@ -158,7 +158,7 @@
     {
       total_transferred_ += bytes_transferred;
       buffers_.consume(bytes_transferred);
- buffers_.set_max_size(detail::adapt_completion_condition_result(
+ buffers_.prepare(detail::adapt_completion_condition_result(
             completion_condition_(ec, total_transferred_)));
       if (buffers_.begin() == buffers_.end())
       {
@@ -225,7 +225,7 @@
 
   boost::system::error_code ec;
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   if (tmp.begin() == tmp.end())
   {

Modified: branches/release/boost/asio/impl/write.ipp
==============================================================================
--- branches/release/boost/asio/impl/write.ipp (original)
+++ branches/release/boost/asio/impl/write.ipp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -19,6 +19,7 @@
 
 #include <boost/asio/buffer.hpp>
 #include <boost/asio/completion_condition.hpp>
+#include <boost/asio/detail/base_from_completion_cond.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
@@ -37,14 +38,14 @@
   boost::asio::detail::consuming_buffers<
     const_buffer, ConstBufferSequence> tmp(buffers);
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   while (tmp.begin() != tmp.end())
   {
     std::size_t bytes_transferred = s.write_some(tmp, ec);
     tmp.consume(bytes_transferred);
     total_transferred += bytes_transferred;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
           completion_condition(ec, total_transferred)));
   }
   return total_transferred;
@@ -111,51 +112,164 @@
 {
   template <typename AsyncWriteStream, typename ConstBufferSequence,
       typename CompletionCondition, typename WriteHandler>
- class write_handler
+ class write_op
+ : detail::base_from_completion_cond<CompletionCondition>
   {
   public:
- typedef boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> buffers_type;
-
- write_handler(AsyncWriteStream& stream, const buffers_type& buffers,
+ write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
         CompletionCondition completion_condition, WriteHandler handler)
- : stream_(stream),
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
         buffers_(buffers),
         total_transferred_(0),
- completion_condition_(completion_condition),
- handler_(handler)
+ handler_(handler),
+ start_(true)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ switch (start_)
+ {
+ case true: start_ = false;
+ buffers_.prepare(this->check(ec, total_transferred_));
+ for (;;)
+ {
+ stream_.async_write_some(buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
+ handler_(ec, total_transferred_);
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ bool start_;
+ };
+
+ template <typename AsyncWriteStream,
+ typename CompletionCondition, typename WriteHandler>
+ class write_op<AsyncWriteStream, boost::asio::mutable_buffers_1,
+ CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_op(AsyncWriteStream& stream,
+ const boost::asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler),
+ start_(true)
     {
     }
 
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred)
     {
- total_transferred_ += bytes_transferred;
- buffers_.consume(bytes_transferred);
- buffers_.set_max_size(detail::adapt_completion_condition_result(
- completion_condition_(ec, total_transferred_)));
- if (buffers_.begin() == buffers_.end())
+ std::size_t n = 0;
+ switch (start_)
       {
+ case true: start_ = false;
+ n = this->check(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_write_some(boost::asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check(ec, total_transferred_)) == 0
+ || total_transferred_ == boost::asio::buffer_size(buffer_))
+ break;
+ }
+
         handler_(ec, total_transferred_);
       }
- else
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ boost::asio::mutable_buffer buffer_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ bool start_;
+ };
+
+ template <typename AsyncWriteStream,
+ typename CompletionCondition, typename WriteHandler>
+ class write_op<AsyncWriteStream, boost::asio::const_buffers_1,
+ CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_op(AsyncWriteStream& stream,
+ const boost::asio::const_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler),
+ start_(true)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ std::size_t n = 0;
+ switch (start_)
       {
- stream_.async_write_some(buffers_, *this);
+ case true: start_ = false;
+ n = this->check(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_write_some(boost::asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check(ec, total_transferred_)) == 0
+ || total_transferred_ == boost::asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, total_transferred_);
       }
     }
 
   //private:
     AsyncWriteStream& stream_;
- buffers_type buffers_;
+ boost::asio::const_buffer buffer_;
     std::size_t total_transferred_;
- CompletionCondition completion_condition_;
     WriteHandler handler_;
+ bool start_;
   };
 
   template <typename AsyncWriteStream, typename ConstBufferSequence,
       typename CompletionCondition, typename WriteHandler>
   inline void* asio_handler_allocate(std::size_t size,
- write_handler<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence,
         CompletionCondition, WriteHandler>* this_handler)
   {
     return boost_asio_handler_alloc_helpers::allocate(
@@ -165,7 +279,7 @@
   template <typename AsyncWriteStream, typename ConstBufferSequence,
       typename CompletionCondition, typename WriteHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
- write_handler<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence,
         CompletionCondition, WriteHandler>* this_handler)
   {
     boost_asio_handler_alloc_helpers::deallocate(
@@ -176,7 +290,7 @@
       typename ConstBufferSequence, typename CompletionCondition,
       typename WriteHandler>
   inline void asio_handler_invoke(const Function& function,
- write_handler<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence,
         CompletionCondition, WriteHandler>* this_handler)
   {
     boost_asio_handler_invoke_helpers::invoke(
@@ -189,24 +303,10 @@
 inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
     CompletionCondition completion_condition, WriteHandler handler)
 {
- boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> tmp(buffers);
-
- boost::system::error_code ec;
- std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- if (tmp.begin() == tmp.end())
- {
- s.get_io_service().post(detail::bind_handler(
- handler, ec, total_transferred));
- return;
- }
-
- s.async_write_some(tmp,
- detail::write_handler<AsyncWriteStream, ConstBufferSequence,
- CompletionCondition, WriteHandler>(
- s, tmp, completion_condition, handler));
+ detail::write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>(
+ s, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0);
 }
 
 template <typename AsyncWriteStream, typename ConstBufferSequence,

Modified: branches/release/boost/asio/impl/write_at.ipp
==============================================================================
--- branches/release/boost/asio/impl/write_at.ipp (original)
+++ branches/release/boost/asio/impl/write_at.ipp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -38,7 +38,7 @@
   boost::asio::detail::consuming_buffers<
     const_buffer, ConstBufferSequence> tmp(buffers);
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   while (tmp.begin() != tmp.end())
   {
@@ -46,7 +46,7 @@
         offset + total_transferred, tmp, ec);
     tmp.consume(bytes_transferred);
     total_transferred += bytes_transferred;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
           completion_condition(ec, total_transferred)));
   }
   return total_transferred;
@@ -142,7 +142,7 @@
     {
       total_transferred_ += bytes_transferred;
       buffers_.consume(bytes_transferred);
- buffers_.set_max_size(detail::adapt_completion_condition_result(
+ buffers_.prepare(detail::adapt_completion_condition_result(
             completion_condition_(ec, total_transferred_)));
       if (buffers_.begin() == buffers_.end())
       {
@@ -207,7 +207,7 @@
 
   boost::system::error_code ec;
   std::size_t total_transferred = 0;
- tmp.set_max_size(detail::adapt_completion_condition_result(
+ tmp.prepare(detail::adapt_completion_condition_result(
         completion_condition(ec, total_transferred)));
   if (tmp.begin() == tmp.end())
   {

Modified: branches/release/boost/asio/io_service.hpp
==============================================================================
--- branches/release/boost/asio/io_service.hpp (original)
+++ branches/release/boost/asio/io_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -26,11 +26,8 @@
 #include <boost/system/error_code.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
-#include <boost/asio/detail/dev_poll_reactor_fwd.hpp>
-#include <boost/asio/detail/epoll_reactor_fwd.hpp>
-#include <boost/asio/detail/kqueue_reactor_fwd.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/select_reactor_fwd.hpp>
+#include <boost/asio/detail/reactor_fwd.hpp>
 #include <boost/asio/detail/service_registry_fwd.hpp>
 #include <boost/asio/detail/signal_init.hpp>
 #include <boost/asio/detail/task_io_service_fwd.hpp>
@@ -46,6 +43,12 @@
 template <typename Service> void add_service(io_service& ios, Service* svc);
 template <typename Service> bool has_service(io_service& ios);
 
+#if defined(BOOST_ASIO_HAS_IOCP)
+namespace detail { typedef win_iocp_io_service io_service_impl; }
+#else
+namespace detail { typedef task_io_service<reactor> io_service_impl; }
+#endif
+
 /// Provides core I/O functionality.
 /**
  * The io_service class provides the core I/O functionality for users of the
@@ -178,18 +181,9 @@
   : private noncopyable
 {
 private:
- // The type of the platform-specific implementation.
+ typedef detail::io_service_impl impl_type;
 #if defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::win_iocp_io_service impl_type;
   friend class detail::win_iocp_overlapped_ptr;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::task_io_service<detail::kqueue_reactor<false> > impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::task_io_service<detail::dev_poll_reactor<false> > impl_type;
-#else
- typedef detail::task_io_service<detail::select_reactor<false> > impl_type;
 #endif
 
 public:
@@ -606,9 +600,14 @@
   virtual void shutdown_service() = 0;
 
   friend class boost::asio::detail::service_registry;
+ struct key
+ {
+ key() : type_info_(0), id_(0) {}
+ const std::type_info* type_info_;
+ const boost::asio::io_service::id* id_;
+ } key_;
+
   boost::asio::io_service& owner_;
- const std::type_info* type_info_;
- const boost::asio::io_service::id* id_;
   service* next_;
 };
 

Modified: branches/release/boost/asio/ip/basic_resolver_iterator.hpp
==============================================================================
--- branches/release/boost/asio/ip/basic_resolver_iterator.hpp (original)
+++ branches/release/boost/asio/ip/basic_resolver_iterator.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -18,8 +18,7 @@
 #include <boost/asio/detail/push_options.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
-#include <boost/iterator/iterator_facade.hpp>
-#include <boost/optional.hpp>
+#include <boost/iterator.hpp>
 #include <boost/shared_ptr.hpp>
 #include <cstring>
 #include <string>
@@ -48,14 +47,18 @@
  */
 template <typename InternetProtocol>
 class basic_resolver_iterator
- : public boost::iterator_facade<
- basic_resolver_iterator<InternetProtocol>,
- const basic_resolver_entry<InternetProtocol>,
- boost::forward_traversal_tag>
+#if defined(GENERATING_DOCUMENTATION)
+ : public std::iterator<
+#else // defined(GENERATING_DOCUMENTATION)
+ : public boost::iterator<
+#endif // defined(GENERATING_DOCUMENTATION)
+ std::forward_iterator_tag,
+ const basic_resolver_entry<InternetProtocol> >
 {
 public:
   /// Default constructor creates an end iterator.
   basic_resolver_iterator()
+ : index_(0)
   {
   }
 
@@ -91,11 +94,6 @@
       address_info = address_info->ai_next;
     }
 
- if (iter.values_->size())
- iter.iter_ = iter.values_->begin();
- else
- iter.values_.reset();
-
     return iter;
   }
 
@@ -109,21 +107,58 @@
     iter.values_->push_back(
         basic_resolver_entry<InternetProtocol>(
           endpoint, host_name, service_name));
- iter.iter_ = iter.values_->begin();
     return iter;
   }
 
-private:
- friend class boost::iterator_core_access;
+ /// Dereference an iterator.
+ const basic_resolver_entry<InternetProtocol>& operator*() const
+ {
+ return dereference();
+ }
+
+ /// Dereference an iterator.
+ const basic_resolver_entry<InternetProtocol>* operator->() const
+ {
+ return &dereference();
+ }
+
+ /// Increment operator (prefix).
+ basic_resolver_iterator& operator++()
+ {
+ increment();
+ return *this;
+ }
 
+ /// Increment operator (postfix).
+ basic_resolver_iterator operator++(int)
+ {
+ basic_resolver_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ /// Test two iterators for equality.
+ friend bool operator==(const basic_resolver_iterator& a,
+ const basic_resolver_iterator& b)
+ {
+ return a.equal(b);
+ }
+
+ /// Test two iterators for inequality.
+ friend bool operator!=(const basic_resolver_iterator& a,
+ const basic_resolver_iterator& b)
+ {
+ return !a.equal(b);
+ }
+
+private:
   void increment()
   {
- if (++*iter_ == values_->end())
+ if (++index_ == values_->size())
     {
       // Reset state to match a default constructed end iterator.
       values_.reset();
- typedef typename values_type::const_iterator values_iterator_type;
- iter_.reset();
+ index_ = 0;
     }
   }
 
@@ -133,18 +168,17 @@
       return true;
     if (values_ != other.values_)
       return false;
- return *iter_ == *other.iter_;
+ return index_ == other.index_;
   }
 
   const basic_resolver_entry<InternetProtocol>& dereference() const
   {
- return **iter_;
+ return (*values_)[index_];
   }
 
   typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
- typedef typename values_type::const_iterator values_iter_type;
   boost::shared_ptr<values_type> values_;
- boost::optional<values_iter_type> iter_;
+ std::size_t index_;
 };
 
 } // namespace ip

Modified: branches/release/boost/asio/posix/stream_descriptor_service.hpp
==============================================================================
--- branches/release/boost/asio/posix/stream_descriptor_service.hpp (original)
+++ branches/release/boost/asio/posix/stream_descriptor_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -35,19 +35,7 @@
 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
   || defined(GENERATING_DOCUMENTATION)
 
-#if defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/reactive_descriptor_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/reactive_descriptor_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/reactive_descriptor_service.hpp>
-#else
-# include <boost/asio/detail/select_reactor.hpp>
-# include <boost/asio/detail/reactive_descriptor_service.hpp>
-#endif
+#include <boost/asio/detail/reactive_descriptor_service.hpp>
 
 namespace boost {
 namespace asio {
@@ -69,19 +57,7 @@
 
 private:
   // The type of the platform-specific implementation.
-#if defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_descriptor_service<
- detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_descriptor_service<
- detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_descriptor_service<
- detail::dev_poll_reactor<false> > service_impl_type;
-#else
- typedef detail::reactive_descriptor_service<
- detail::select_reactor<false> > service_impl_type;
-#endif
+ typedef detail::reactive_descriptor_service service_impl_type;
 
 public:
   /// The type of a stream descriptor implementation.
@@ -101,13 +77,14 @@
   /// Construct a new stream descriptor service for the specified io_service.
   explicit stream_descriptor_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<stream_descriptor_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined descriptorr objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new stream descriptor implementation.
@@ -196,8 +173,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace posix

Modified: branches/release/boost/asio/raw_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/raw_socket_service.hpp (original)
+++ branches/release/boost/asio/raw_socket_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -28,17 +28,7 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 # include <boost/asio/detail/win_iocp_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
 #else
-# include <boost/asio/detail/select_reactor.hpp>
 # include <boost/asio/detail/reactive_socket_service.hpp>
 #endif
 
@@ -70,18 +60,8 @@
   // The type of the platform-specific implementation.
 #if defined(BOOST_ASIO_HAS_IOCP)
   typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_socket_service<
- Protocol, detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::dev_poll_reactor<false> > service_impl_type;
 #else
- typedef detail::reactive_socket_service<
- Protocol, detail::select_reactor<false> > service_impl_type;
+ typedef detail::reactive_socket_service<Protocol> service_impl_type;
 #endif
 
 public:
@@ -103,13 +83,14 @@
   explicit raw_socket_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         raw_socket_service<Protocol> >(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new raw socket implementation.
@@ -324,8 +305,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Modified: branches/release/boost/asio/serial_port_service.hpp
==============================================================================
--- branches/release/boost/asio/serial_port_service.hpp (original)
+++ branches/release/boost/asio/serial_port_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -54,18 +54,8 @@
   // The type of the platform-specific implementation.
 #if defined(BOOST_ASIO_HAS_IOCP)
   typedef detail::win_iocp_serial_port_service service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_serial_port_service<
- detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_serial_port_service<
- detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_serial_port_service<
- detail::dev_poll_reactor<false> > service_impl_type;
 #else
- typedef detail::reactive_serial_port_service<
- detail::select_reactor<false> > service_impl_type;
+ typedef detail::reactive_serial_port_service service_impl_type;
 #endif
 
 public:
@@ -86,13 +76,14 @@
   /// Construct a new serial port service for the specified io_service.
   explicit serial_port_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<serial_port_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new serial port implementation.
@@ -203,8 +194,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Modified: branches/release/boost/asio/socket_acceptor_service.hpp
==============================================================================
--- branches/release/boost/asio/socket_acceptor_service.hpp (original)
+++ branches/release/boost/asio/socket_acceptor_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -24,17 +24,7 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 # include <boost/asio/detail/win_iocp_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
 #else
-# include <boost/asio/detail/select_reactor.hpp>
 # include <boost/asio/detail/reactive_socket_service.hpp>
 #endif
 
@@ -66,18 +56,8 @@
   // The type of the platform-specific implementation.
 #if defined(BOOST_ASIO_HAS_IOCP)
   typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_socket_service<
- Protocol, detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::dev_poll_reactor<false> > service_impl_type;
 #else
- typedef detail::reactive_socket_service<
- Protocol, detail::select_reactor<false> > service_impl_type;
+ typedef detail::reactive_socket_service<Protocol> service_impl_type;
 #endif
 
 public:
@@ -99,13 +79,14 @@
   explicit socket_acceptor_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         socket_acceptor_service<Protocol> >(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new socket acceptor implementation.
@@ -226,8 +207,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Modified: branches/release/boost/asio/ssl/detail/openssl_operation.hpp
==============================================================================
--- branches/release/boost/asio/ssl/detail/openssl_operation.hpp (original)
+++ branches/release/boost/asio/ssl/detail/openssl_operation.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -173,7 +173,8 @@
       ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) ==
             SSL_SENT_SHUTDOWN);
 
- if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed)
+ if (is_shut_down_sent && is_shut_down_received
+ && is_operation_done && !is_write_needed)
       // SSL connection is shut down cleanly
       return handler_(boost::system::error_code(), 1);
 

Modified: branches/release/boost/asio/ssl/detail/openssl_stream_service.hpp
==============================================================================
--- branches/release/boost/asio/ssl/detail/openssl_stream_service.hpp (original)
+++ branches/release/boost/asio/ssl/detail/openssl_stream_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -31,6 +31,7 @@
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/strand.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/ssl/basic_context.hpp>
 #include <boost/asio/ssl/stream_base.hpp>
@@ -333,13 +334,22 @@
     size_t bytes_transferred = 0;
     try
     {
- std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ boost::asio::const_buffer buffer =
+ boost::asio::detail::buffer_sequence_adapter<
+ boost::asio::const_buffer, Const_Buffers>::first(buffers);
+
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
       if (buffer_size > max_buffer_size)
         buffer_size = max_buffer_size;
+ else if (buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
 
       boost::function<int (SSL*)> send_func =
         boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
- boost::asio::buffer_cast<const void*>(*buffers.begin()),
+ boost::asio::buffer_cast<const void*>(buffer),
             static_cast<int>(buffer_size));
       openssl_operation<Stream> op(
         send_func,
@@ -367,15 +377,25 @@
   {
     typedef io_handler<Stream, Handler> send_handler;
 
- send_handler* local_handler = new send_handler(handler, get_io_service());
+ boost::asio::const_buffer buffer =
+ boost::asio::detail::buffer_sequence_adapter<
+ boost::asio::const_buffer, Const_Buffers>::first(buffers);
 
- std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
     if (buffer_size > max_buffer_size)
       buffer_size = max_buffer_size;
+ else if (buffer_size == 0)
+ {
+ get_io_service().post(boost::asio::detail::bind_handler(
+ handler, boost::system::error_code(), 0));
+ return;
+ }
+
+ send_handler* local_handler = new send_handler(handler, get_io_service());
 
     boost::function<int (SSL*)> send_func =
       boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
- boost::asio::buffer_cast<const void*>(*buffers.begin()),
+ boost::asio::buffer_cast<const void*>(buffer),
           static_cast<int>(buffer_size));
 
     openssl_operation<Stream>* op = new openssl_operation<Stream>
@@ -407,13 +427,22 @@
     size_t bytes_transferred = 0;
     try
     {
- std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ boost::asio::mutable_buffer buffer =
+ boost::asio::detail::buffer_sequence_adapter<
+ boost::asio::mutable_buffer, Mutable_Buffers>::first(buffers);
+
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
       if (buffer_size > max_buffer_size)
         buffer_size = max_buffer_size;
+ else if (buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
 
       boost::function<int (SSL*)> recv_func =
         boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
- boost::asio::buffer_cast<void*>(*buffers.begin()),
+ boost::asio::buffer_cast<void*>(buffer),
             static_cast<int>(buffer_size));
       openssl_operation<Stream> op(recv_func,
         next_layer,
@@ -441,15 +470,25 @@
   {
     typedef io_handler<Stream, Handler> recv_handler;
 
- recv_handler* local_handler = new recv_handler(handler, get_io_service());
+ boost::asio::mutable_buffer buffer =
+ boost::asio::detail::buffer_sequence_adapter<
+ boost::asio::mutable_buffer, Mutable_Buffers>::first(buffers);
 
- std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
     if (buffer_size > max_buffer_size)
       buffer_size = max_buffer_size;
+ else if (buffer_size == 0)
+ {
+ get_io_service().post(boost::asio::detail::bind_handler(
+ handler, boost::system::error_code(), 0));
+ return;
+ }
+
+ recv_handler* local_handler = new recv_handler(handler, get_io_service());
 
     boost::function<int (SSL*)> recv_func =
       boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
- boost::asio::buffer_cast<void*>(*buffers.begin()),
+ boost::asio::buffer_cast<void*>(buffer),
           static_cast<int>(buffer_size));
 
     openssl_operation<Stream>* op = new openssl_operation<Stream>

Modified: branches/release/boost/asio/stream_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/stream_socket_service.hpp (original)
+++ branches/release/boost/asio/stream_socket_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -28,17 +28,7 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 # include <boost/asio/detail/win_iocp_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_EPOLL)
-# include <boost/asio/detail/epoll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
-# include <boost/asio/detail/kqueue_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
-# include <boost/asio/detail/dev_poll_reactor.hpp>
-# include <boost/asio/detail/reactive_socket_service.hpp>
 #else
-# include <boost/asio/detail/select_reactor.hpp>
 # include <boost/asio/detail/reactive_socket_service.hpp>
 #endif
 
@@ -70,18 +60,8 @@
   // The type of the platform-specific implementation.
 #if defined(BOOST_ASIO_HAS_IOCP)
   typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_EPOLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::epoll_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_KQUEUE)
- typedef detail::reactive_socket_service<
- Protocol, detail::kqueue_reactor<false> > service_impl_type;
-#elif defined(BOOST_ASIO_HAS_DEV_POLL)
- typedef detail::reactive_socket_service<
- Protocol, detail::dev_poll_reactor<false> > service_impl_type;
 #else
- typedef detail::reactive_socket_service<
- Protocol, detail::select_reactor<false> > service_impl_type;
+ typedef detail::reactive_socket_service<Protocol> service_impl_type;
 #endif
 
 public:
@@ -103,13 +83,14 @@
   explicit stream_socket_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         stream_socket_service<Protocol> >(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new stream socket implementation.
@@ -287,8 +268,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace asio

Modified: branches/release/boost/asio/windows/random_access_handle_service.hpp
==============================================================================
--- branches/release/boost/asio/windows/random_access_handle_service.hpp (original)
+++ branches/release/boost/asio/windows/random_access_handle_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -78,13 +78,14 @@
   explicit random_access_handle_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<
         random_access_handle_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new random-access handle implementation.
@@ -165,8 +166,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace windows

Modified: branches/release/boost/asio/windows/stream_handle_service.hpp
==============================================================================
--- branches/release/boost/asio/windows/stream_handle_service.hpp (original)
+++ branches/release/boost/asio/windows/stream_handle_service.hpp 2010-03-17 20:58:47 EDT (Wed, 17 Mar 2010)
@@ -76,13 +76,14 @@
   /// Construct a new stream handle service for the specified io_service.
   explicit stream_handle_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<stream_handle_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+ service_impl_.shutdown_service();
   }
 
   /// Construct a new stream handle implementation.
@@ -163,8 +164,8 @@
   }
 
 private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
 };
 
 } // namespace windows


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