Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69198 - in trunk: boost boost/asio boost/asio/detail boost/asio/detail/impl boost/asio/impl boost/asio/ip libs/asio/doc libs/asio/doc/requirements libs/asio/example/http/server libs/asio/example/http/server2 libs/asio/example/http/server3 libs/asio/example/http/server4 libs/asio/test libs/asio/tools
From: chris_at_[hidden]
Date: 2011-02-22 20:43:32


Author: chris_kohlhoff
Date: 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
New Revision: 69198
URL: http://svn.boost.org/trac/boost/changeset/69198

Log:
Changes for asio version 1.5.1:

* Added support for signal handling, using a new class called
  signal_set. Programs may add one or more signals to the set, and then
  perform an async_wait() operation. The specified handler will be
  called when one of the signals occurs. The same signal number may
  registered with multiple signal_set objects, however the signal number
  must be used only with Asio.

* Added handler tracking, a new debugging aid. When enabled by defining
  BOOST_ASIO_ENABLE_HANDLER_TRACKING, Asio writes debugging output to
  the standard error stream. The output records asynchronous operations
  and the relationships between their handlers. It may be post-processed
  using the included [^handlerviz.pl] tool to create a visual
  representation of the handlers (requires GraphViz).

* Fixed a bug in asio::streambuf where the consume() function did not
  always update the internal buffer pointers correctly. The problem may
  occur when the asio::streambuf is filled with data using the standard
  C++ member functions such as sputn(). (Note: the problem does not
  manifest when the streambuf is populated by the Asio free functions
  read(), async_read(), read_until() or async_read_until().)

* Fixed a bug on kqueue-based platforms, where reactor read operations
  that return false from their perform() function are not correctly
  re-registered with kqueue.

* Modified the buffers_iterator<> and ip::basic_resolver_iterator
  classes so that the value_type typedefs are non-const byte types.

Added:
   trunk/boost/asio/basic_signal_set.hpp (contents, props changed)
   trunk/boost/asio/detail/handler_tracking.hpp (contents, props changed)
   trunk/boost/asio/detail/impl/handler_tracking.ipp (contents, props changed)
   trunk/boost/asio/detail/impl/signal_set_service.ipp (contents, props changed)
   trunk/boost/asio/detail/impl/win_static_mutex.ipp (contents, props changed)
   trunk/boost/asio/detail/null_static_mutex.hpp (contents, props changed)
   trunk/boost/asio/detail/posix_static_mutex.hpp (contents, props changed)
   trunk/boost/asio/detail/signal_handler.hpp (contents, props changed)
   trunk/boost/asio/detail/signal_op.hpp (contents, props changed)
   trunk/boost/asio/detail/signal_set_service.hpp (contents, props changed)
   trunk/boost/asio/detail/static_mutex.hpp (contents, props changed)
   trunk/boost/asio/detail/win_static_mutex.hpp (contents, props changed)
   trunk/boost/asio/signal_set.hpp (contents, props changed)
   trunk/boost/asio/signal_set_service.hpp (contents, props changed)
   trunk/libs/asio/doc/requirements/SignalHandler.qbk (contents, props changed)
   trunk/libs/asio/doc/requirements/SignalSetService.qbk (contents, props changed)
   trunk/libs/asio/example/http/server/main.cpp (contents, props changed)
   trunk/libs/asio/example/http/server2/main.cpp (contents, props changed)
   trunk/libs/asio/example/http/server3/main.cpp (contents, props changed)
   trunk/libs/asio/example/http/server4/main.cpp (contents, props changed)
   trunk/libs/asio/test/basic_signal_set.cpp (contents, props changed)
   trunk/libs/asio/test/basic_streambuf.cpp (contents, props changed)
   trunk/libs/asio/test/signal_set.cpp (contents, props changed)
   trunk/libs/asio/test/signal_set_service.cpp (contents, props changed)
   trunk/libs/asio/test/streambuf.cpp (contents, props changed)
   trunk/libs/asio/tools/
   trunk/libs/asio/tools/handlerviz.pl (contents, props changed)
Removed:
   trunk/libs/asio/example/http/server/posix_main.cpp
   trunk/libs/asio/example/http/server/win_main.cpp
   trunk/libs/asio/example/http/server2/posix_main.cpp
   trunk/libs/asio/example/http/server2/win_main.cpp
   trunk/libs/asio/example/http/server3/posix_main.cpp
   trunk/libs/asio/example/http/server3/win_main.cpp
   trunk/libs/asio/example/http/server4/posix_main.cpp
   trunk/libs/asio/example/http/server4/win_main.cpp
Text files modified:
   trunk/boost/asio.hpp | 3
   trunk/boost/asio/basic_streambuf.hpp | 2
   trunk/boost/asio/buffers_iterator.hpp | 53
   trunk/boost/asio/detail/completion_handler.hpp | 4
   trunk/boost/asio/detail/config.hpp | 12
   trunk/boost/asio/detail/deadline_timer_service.hpp | 6
   trunk/boost/asio/detail/descriptor_read_op.hpp | 4
   trunk/boost/asio/detail/descriptor_write_op.hpp | 4
   trunk/boost/asio/detail/dev_poll_reactor.hpp | 6
   trunk/boost/asio/detail/epoll_reactor.hpp | 13
   trunk/boost/asio/detail/gcc_arm_fenced_block.hpp | 5
   trunk/boost/asio/detail/handler_type_requirements.hpp | 24
   trunk/boost/asio/detail/impl/dev_poll_reactor.ipp | 20
   trunk/boost/asio/detail/impl/epoll_reactor.ipp | 74 +
   trunk/boost/asio/detail/impl/eventfd_select_interrupter.ipp | 27
   trunk/boost/asio/detail/impl/kqueue_reactor.ipp | 33
   trunk/boost/asio/detail/impl/pipe_select_interrupter.ipp | 5
   trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp | 8
   trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp | 6
   trunk/boost/asio/detail/impl/resolver_service_base.ipp | 7
   trunk/boost/asio/detail/impl/select_reactor.ipp | 12
   trunk/boost/asio/detail/impl/strand_service.hpp | 4
   trunk/boost/asio/detail/impl/task_io_service.hpp | 16
   trunk/boost/asio/detail/impl/task_io_service.ipp | 1
   trunk/boost/asio/detail/impl/win_iocp_handle_service.ipp | 10
   trunk/boost/asio/detail/impl/win_iocp_io_service.hpp | 16
   trunk/boost/asio/detail/impl/win_iocp_io_service.ipp | 1
   trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp | 9
   trunk/boost/asio/detail/kqueue_reactor.hpp | 6
   trunk/boost/asio/detail/reactive_descriptor_service.hpp | 10
   trunk/boost/asio/detail/reactive_null_buffers_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_accept_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_connect_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_recv_op.hpp | 6
   trunk/boost/asio/detail/reactive_socket_recvfrom_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_recvmsg_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_send_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_sendto_op.hpp | 4
   trunk/boost/asio/detail/reactive_socket_service.hpp | 15
   trunk/boost/asio/detail/reactive_socket_service_base.hpp | 16
   trunk/boost/asio/detail/resolve_endpoint_op.hpp | 4
   trunk/boost/asio/detail/resolve_op.hpp | 4
   trunk/boost/asio/detail/resolver_service.hpp | 4
   trunk/boost/asio/detail/select_reactor.hpp | 6
   trunk/boost/asio/detail/task_io_service_operation.hpp | 3
   trunk/boost/asio/detail/wait_handler.hpp | 4
   trunk/boost/asio/detail/win_iocp_handle_read_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_handle_service.hpp | 32
   trunk/boost/asio/detail/win_iocp_handle_write_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_null_buffers_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_operation.hpp | 2
   trunk/boost/asio/detail/win_iocp_overlapped_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_overlapped_ptr.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_accept_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_recv_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_send_op.hpp | 4
   trunk/boost/asio/detail/win_iocp_socket_service.hpp | 14
   trunk/boost/asio/detail/win_iocp_socket_service_base.hpp | 16
   trunk/boost/asio/impl/src.hpp | 3
   trunk/boost/asio/ip/basic_resolver_iterator.hpp | 25
   trunk/boost/asio/placeholders.hpp | 16
   trunk/boost/asio/version.hpp | 2
   trunk/libs/asio/doc/examples.qbk | 12
   trunk/libs/asio/doc/quickref.xml | 27
   trunk/libs/asio/doc/reference.qbk | 1942 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/asio/doc/reference.xsl | 2
   trunk/libs/asio/example/http/server/Jamfile | 3
   trunk/libs/asio/example/http/server/Jamfile.v2 | 3
   trunk/libs/asio/example/http/server/server.cpp | 12
   trunk/libs/asio/example/http/server/server.hpp | 3
   trunk/libs/asio/example/http/server2/Jamfile | 3
   trunk/libs/asio/example/http/server2/Jamfile.v2 | 3
   trunk/libs/asio/example/http/server3/Jamfile | 3
   trunk/libs/asio/example/http/server3/Jamfile.v2 | 3
   trunk/libs/asio/example/http/server4/Jamfile | 3
   trunk/libs/asio/example/http/server4/Jamfile.v2 | 3
   trunk/libs/asio/test/Jamfile | 5
   trunk/libs/asio/test/Jamfile.v2 | 10
   80 files changed, 2574 insertions(+), 104 deletions(-)

Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp (original)
+++ trunk/boost/asio.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -23,6 +23,7 @@
 #include <boost/asio/basic_raw_socket.hpp>
 #include <boost/asio/basic_seq_packet_socket.hpp>
 #include <boost/asio/basic_serial_port.hpp>
+#include <boost/asio/basic_signal_set.hpp>
 #include <boost/asio/basic_socket_acceptor.hpp>
 #include <boost/asio/basic_socket_iostream.hpp>
 #include <boost/asio/basic_socket_streambuf.hpp>
@@ -82,6 +83,8 @@
 #include <boost/asio/serial_port.hpp>
 #include <boost/asio/serial_port_base.hpp>
 #include <boost/asio/serial_port_service.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/signal_set_service.hpp>
 #include <boost/asio/socket_acceptor_service.hpp>
 #include <boost/asio/socket_base.hpp>
 #include <boost/asio/strand.hpp>

Added: trunk/boost/asio/basic_signal_set.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/basic_signal_set.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,384 @@
+//
+// basic_signal_set.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_BASIC_SIGNAL_SET_HPP
+#define BOOST_ASIO_BASIC_SIGNAL_SET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/signal_set_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides signal functionality.
+/**
+ * The basic_signal_set class template provides the ability to perform an
+ * asynchronous wait for one or more signals to occur.
+ *
+ * Most applications will use the boost::asio::signal_set typedef.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Performing an asynchronous wait:
+ * @code
+ * void handler(
+ * const boost::system::error_code& error,
+ * int signal_number)
+ * {
+ * if (!error)
+ * {
+ * // A signal occurred.
+ * }
+ * }
+ *
+ * ...
+ *
+ * // Construct a signal set registered for process termination.
+ * boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
+ *
+ * // Start an asynchronous wait for one of the signals to occur.
+ * signals.async_wait(handler);
+ * @endcode
+ *
+ * @par Queueing of signal notifications
+ *
+ * If a signal is registered with a signal_set, and the signal occurs when
+ * there are no waiting handlers, then the signal notification is queued. The
+ * next async_wait operation on that signal_set will dequeue the notification.
+ * If multiple notifications are queued, subsequent async_wait operations
+ * dequeue them one at a time. Signal notifications are dequeued in order of
+ * ascending signal number.
+ *
+ * If a signal number is removed from a signal_set (using the @c remove or @c
+ * erase member functions) then any queued notifications for that signal are
+ * discarded.
+ *
+ * @par Multiple registration of signals
+ *
+ * The same signal number may be registered with different signal_set objects.
+ * When the signal occurs, one handler is called for each signal_set object.
+ *
+ * Note that multiple registration only works for signals that are registered
+ * using Asio. The application must not also register a signal handler using
+ * functions such as @c signal() or @c sigaction().
+ *
+ * @par Signal masking on POSIX platforms
+ *
+ * POSIX allows signals to be blocked using functions such as @c sigprocmask()
+ * and @c pthread_sigmask(). For signals to be delivered, programs must ensure
+ * that any signals registered using signal_set objects are unblocked in at
+ * least one thread.
+ */
+template <typename SignalSetService = signal_set_service>
+class basic_signal_set
+ : public basic_io_object<SignalSetService>
+{
+public:
+ /// Construct a signal set without adding any signals.
+ /**
+ * This constructor creates a signal set without registering for any signals.
+ *
+ * @param io_service The io_service object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ */
+ explicit basic_signal_set(boost::asio::io_service& io_service)
+ : basic_io_object<SignalSetService>(io_service)
+ {
+ }
+
+ /// Construct a signal set and add one signal.
+ /**
+ * This constructor creates a signal set and registers for one signal.
+ *
+ * @param io_service The io_service object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_service);
+ * signals.add(signal_number_1); @endcode
+ */
+ basic_signal_set(boost::asio::io_service& io_service, int signal_number_1)
+ : basic_io_object<SignalSetService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.add(this->implementation, signal_number_1, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a signal set and add two signals.
+ /**
+ * This constructor creates a signal set and registers for two signals.
+ *
+ * @param io_service The io_service object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The first signal number to be added.
+ *
+ * @param signal_number_2 The second signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_service);
+ * signals.add(signal_number_1);
+ * signals.add(signal_number_2); @endcode
+ */
+ basic_signal_set(boost::asio::io_service& io_service, int signal_number_1,
+ int signal_number_2)
+ : basic_io_object<SignalSetService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.add(this->implementation, signal_number_1, ec);
+ boost::asio::detail::throw_error(ec);
+ this->service.add(this->implementation, signal_number_2, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a signal set and add three signals.
+ /**
+ * This constructor creates a signal set and registers for three signals.
+ *
+ * @param io_service The io_service object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The first signal number to be added.
+ *
+ * @param signal_number_2 The second signal number to be added.
+ *
+ * @param signal_number_3 The third signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_service);
+ * signals.add(signal_number_1);
+ * signals.add(signal_number_2);
+ * signals.add(signal_number_3); @endcode
+ */
+ basic_signal_set(boost::asio::io_service& io_service, int signal_number_1,
+ int signal_number_2, int signal_number_3)
+ : basic_io_object<SignalSetService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.add(this->implementation, signal_number_1, ec);
+ boost::asio::detail::throw_error(ec);
+ this->service.add(this->implementation, signal_number_2, ec);
+ boost::asio::detail::throw_error(ec);
+ this->service.add(this->implementation, signal_number_3, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Add a signal to a signal_set.
+ /**
+ * This function adds the specified signal to the set. It has no effect if the
+ * signal is already in the set.
+ *
+ * @param signal_number The signal to be added to the set.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void add(int signal_number)
+ {
+ boost::system::error_code ec;
+ this->service.add(this->implementation, signal_number, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Add a signal to a signal_set.
+ /**
+ * This function adds the specified signal to the set. It has no effect if the
+ * signal is already in the set.
+ *
+ * @param signal_number The signal to be added to the set.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code add(int signal_number,
+ boost::system::error_code& ec)
+ {
+ return this->service.add(this->implementation, signal_number, ec);
+ }
+
+ /// Remove a signal from a signal_set.
+ /**
+ * This function removes the specified signal from the set. It has no effect
+ * if the signal is not in the set.
+ *
+ * @param signal_number The signal to be removed from the set.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Removes any notifications that have been queued for the specified
+ * signal number.
+ */
+ void remove(int signal_number)
+ {
+ boost::system::error_code ec;
+ this->service.remove(this->implementation, signal_number, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Remove a signal from a signal_set.
+ /**
+ * This function removes the specified signal from the set. It has no effect
+ * if the signal is not in the set.
+ *
+ * @param signal_number The signal to be removed from the set.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Removes any notifications that have been queued for the specified
+ * signal number.
+ */
+ boost::system::error_code remove(int signal_number,
+ boost::system::error_code& ec)
+ {
+ return this->service.remove(this->implementation, signal_number, ec);
+ }
+
+ /// Remove all signals from a signal_set.
+ /**
+ * This function removes all signals from the set. It has no effect if the set
+ * is already empty.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Removes all queued notifications.
+ */
+ void clear()
+ {
+ boost::system::error_code ec;
+ this->service.clear(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Remove all signals from a signal_set.
+ /**
+ * This function removes all signals from the set. It has no effect if the set
+ * is already empty.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Removes all queued notifications.
+ */
+ boost::system::error_code clear(boost::system::error_code& ec)
+ {
+ return this->service.clear(this->implementation, ec);
+ }
+
+ /// Cancel all operations associated with the signal set.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the signal set. The handler for each cancelled
+ * operation will be invoked with the boost::asio::error::operation_aborted
+ * error code.
+ *
+ * Cancellation does not alter the set of registered signals.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note If a registered signal occurred before cancel() is called, then the
+ * handlers for asynchronous wait operations will:
+ *
+ * @li have already been invoked; or
+ *
+ * @li have been queued for invocation in the near future.
+ *
+ * These handlers can no longer be cancelled, and therefore are passed an
+ * error code that indicates the successful completion of the wait operation.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all operations associated with the signal set.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the signal set. The handler for each cancelled
+ * operation will be invoked with the boost::asio::error::operation_aborted
+ * error code.
+ *
+ * Cancellation does not alter the set of registered signals.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note If a registered signal occurred before cancel() is called, then the
+ * handlers for asynchronous wait operations will:
+ *
+ * @li have already been invoked; or
+ *
+ * @li have been queued for invocation in the near future.
+ *
+ * These handlers can no longer be cancelled, and therefore are passed an
+ * error code that indicates the successful completion of the wait operation.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Start an asynchronous operation to wait for a signal to be delivered.
+ /**
+ * This function may be used to initiate an asynchronous wait against the
+ * signal set. It always returns immediately.
+ *
+ * For each call to async_wait(), the supplied handler will be called exactly
+ * once. The handler will be called when:
+ *
+ * @li One of the registered signals in the signal set occurs; or
+ *
+ * @li The signal set was cancelled, in which case the handler is passed the
+ * error code boost::asio::error::operation_aborted.
+ *
+ * @param handler The handler to be called when the signal occurs. Copies
+ * will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * int signal_number // Indicates which signal occurred.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename SignalHandler>
+ void async_wait(SignalHandler handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a SignalHandler.
+ BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
+
+ this->service.async_wait(this->implementation,
+ BOOST_ASIO_MOVE_CAST(SignalHandler)(handler));
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP

Modified: trunk/boost/asio/basic_streambuf.hpp
==============================================================================
--- trunk/boost/asio/basic_streambuf.hpp (original)
+++ trunk/boost/asio/basic_streambuf.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -237,6 +237,8 @@
    */
   void consume(std::size_t n)
   {
+ if (egptr() < pptr())
+ setg(&buffer_[0], gptr(), pptr());
     if (gptr() + n > pptr())
       n = pptr() - gptr();
     gbump(static_cast<int>(n));

Modified: trunk/boost/asio/buffers_iterator.hpp
==============================================================================
--- trunk/boost/asio/buffers_iterator.hpp (original)
+++ trunk/boost/asio/buffers_iterator.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -17,9 +17,9 @@
 
 #include <boost/asio/detail/config.hpp>
 #include <cstddef>
+#include <iterator>
 #include <boost/assert.hpp>
 #include <boost/detail/workaround.hpp>
-#include <boost/iterator.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/add_const.hpp>
 #include <boost/asio/buffer.hpp>
@@ -73,18 +73,47 @@
 /// A random access iterator over the bytes in a buffer sequence.
 template <typename BufferSequence, typename ByteType = char>
 class buffers_iterator
- : public boost::iterator<
- std::random_access_iterator_tag,
- typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::byte_type>
 {
 private:
   typedef typename detail::buffers_iterator_types<
       BufferSequence, ByteType>::buffer_type buffer_type;
- typedef typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::byte_type byte_type;
 
 public:
+ /// The type used for the distance between two iterators.
+ typedef std::ptrdiff_t difference_type;
+
+ /// The type of the value pointed to by the iterator.
+ typedef ByteType value_type;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// The type of the result of applying operator->() to the iterator.
+ /**
+ * If the buffer sequence stores buffer objects that are convertible to
+ * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
+ * pointer to a const ByteType.
+ */
+ typedef const_or_non_const_ByteType* pointer;
+#else // defined(GENERATING_DOCUMENTATION)
+ typedef typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::byte_type* pointer;
+#endif // defined(GENERATING_DOCUMENTATION)
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// The type of the result of applying operator*() to the iterator.
+ /**
+ * If the buffer sequence stores buffer objects that are convertible to
+ * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
+ * reference to a const ByteType.
+ */
+ typedef const_or_non_const_ByteType& reference;
+#else // defined(GENERATING_DOCUMENTATION)
+ typedef typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::byte_type& reference;
+#endif // defined(GENERATING_DOCUMENTATION)
+
+ /// The iterator category.
+ typedef std::random_access_iterator_tag iterator_category;
+
   /// Default constructor. Creates an iterator in an undefined state.
   buffers_iterator()
     : current_buffer_(),
@@ -136,19 +165,19 @@
   }
 
   /// Dereference an iterator.
- byte_type& operator*() const
+ reference operator*() const
   {
     return dereference();
   }
 
   /// Dereference an iterator.
- byte_type* operator->() const
+ pointer operator->() const
   {
     return &dereference();
   }
 
   /// Access an individual element.
- byte_type& operator[](std::ptrdiff_t difference) const
+ reference operator[](std::ptrdiff_t difference) const
   {
     buffers_iterator tmp(*this);
     tmp.advance(difference);
@@ -271,9 +300,9 @@
 
 private:
   // Dereference the iterator.
- byte_type& dereference() const
+ reference dereference() const
   {
- return buffer_cast<byte_type*>(current_buffer_)[current_buffer_position_];
+ return buffer_cast<pointer>(current_buffer_)[current_buffer_position_];
   }
 
   // Compare two iterators for equality.

Modified: trunk/boost/asio/detail/completion_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/completion_handler.hpp (original)
+++ trunk/boost/asio/detail/completion_handler.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -46,6 +46,8 @@
     completion_handler* h(static_cast<completion_handler*>(base));
     ptr p = { boost::addressof(h->handler_), h, h };
 
+ BOOST_ASIO_HANDLER_COMPLETION((h));
+
     // 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
@@ -60,7 +62,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN(());
       boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/config.hpp
==============================================================================
--- trunk/boost/asio/detail/config.hpp (original)
+++ trunk/boost/asio/detail/config.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -74,11 +74,6 @@
 # endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
 # endif // defined(__GNUC__)
-# if defined(BOOST_MSVC)
-# if (_MSC_VER >= 1600)
-# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR
-# endif // (_MSC_VER >= 1600)
-# endif // defined(BOOST_MSVC)
 #endif // !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR)
 
 // Windows: target OS version.
@@ -237,4 +232,11 @@
 # endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 #endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS)
 
+// Can use sigaction() instead of signal().
+#if !defined(BOOST_ASIO_DISABLE_SIGACTION)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# define BOOST_ASIO_HAS_SIGACTION 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_SIGACTION)
+
 #endif // BOOST_ASIO_DETAIL_CONFIG_HPP

Modified: trunk/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- trunk/boost/asio/detail/deadline_timer_service.hpp (original)
+++ trunk/boost/asio/detail/deadline_timer_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -101,6 +101,8 @@
       return 0;
     }
 
+ BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel"));
+
     std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
     impl.might_have_pending_waits = false;
     ec = boost::system::error_code();
@@ -117,6 +119,8 @@
       return 0;
     }
 
+ BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel_one"));
+
     std::size_t count = scheduler_.cancel_timer(
         timer_queue_, impl.timer_data, 1);
     if (count == 0)
@@ -185,6 +189,8 @@
 
     impl.might_have_pending_waits = true;
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "deadline_timer", &impl, "async_wait"));
+
     scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
     p.v = p.p = 0;
   }

Modified: trunk/boost/asio/detail/descriptor_read_op.hpp
==============================================================================
--- trunk/boost/asio/detail/descriptor_read_op.hpp (original)
+++ trunk/boost/asio/detail/descriptor_read_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -82,6 +82,8 @@
     descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -97,7 +99,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/descriptor_write_op.hpp
==============================================================================
--- trunk/boost/asio/detail/descriptor_write_op.hpp (original)
+++ trunk/boost/asio/detail/descriptor_write_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -82,6 +82,8 @@
     descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -97,7 +99,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/dev_poll_reactor.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -71,6 +71,12 @@
   // code on failure.
   BOOST_ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
 
+ // Register a descriptor with an associated single operation. Returns 0 on
+ // success, system error code on failure.
+ BOOST_ASIO_DECL int register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ per_descriptor_data& descriptor_data, reactor_op* op);
+
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op)
   {

Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -78,6 +78,12 @@
   BOOST_ASIO_DECL int register_descriptor(socket_type descriptor,
       per_descriptor_data& descriptor_data);
 
+ // Register a descriptor with an associated single operation. Returns 0 on
+ // success, system error code on failure.
+ BOOST_ASIO_DECL int register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ per_descriptor_data& descriptor_data, reactor_op* op);
+
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op)
   {
@@ -87,8 +93,8 @@
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
- per_descriptor_data& descriptor_data,
- reactor_op* op, bool allow_speculative);
+ per_descriptor_data& descriptor_data, reactor_op* op,
+ bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
@@ -137,6 +143,9 @@
   // cannot be created.
   BOOST_ASIO_DECL static int do_epoll_create();
 
+ // Create the timerfd file descriptor. Does not throw.
+ BOOST_ASIO_DECL static int do_timerfd_create();
+
   // Helper function to add a new timer queue.
   BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
 

Modified: trunk/boost/asio/detail/gcc_arm_fenced_block.hpp
==============================================================================
--- trunk/boost/asio/detail/gcc_arm_fenced_block.hpp (original)
+++ trunk/boost/asio/detail/gcc_arm_fenced_block.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -57,9 +57,14 @@
     || defined(__ARM_ARCH_6Z__) \
     || defined(__ARM_ARCH_6ZK__) \
     || defined(__ARM_ARCH_6T2__)
+# if defined(__thumb__)
+ // This is just a placeholder and almost certainly not sufficient.
+ __asm__ __volatile__ ("" : : : "memory");
+# else // defined(__thumb__)
     int a = 0, b = 0;
     __asm__ __volatile__ ("swp %0, %1, [%2]"
         : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc");
+# endif // defined(__thumb__)
 #else
     // ARMv7 and later.
     __asm__ __volatile__ ("dmb" : : : "memory");

Added: trunk/boost/asio/detail/handler_tracking.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/handler_tracking.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,161 @@
+//
+// detail/handler_tracking.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_TRACKING_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TRACKING_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+# include <boost/cstdint.hpp>
+# include <boost/system/error_code.hpp>
+# include <boost/asio/detail/static_mutex.hpp>
+# include <boost/asio/detail/tss_ptr.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+class handler_tracking
+{
+public:
+ class completion;
+
+ // Base class for objects containing tracked handlers.
+ class tracked_handler
+ {
+ private:
+ // Only the handler_tracking class will have access to the id.
+ friend class handler_tracking;
+ friend class completion;
+ boost::uint64_t id_;
+
+ protected:
+ // Constructor initialises with no id.
+ tracked_handler() : id_(0) {}
+
+ // Prevent deletion through this type.
+ ~tracked_handler() {}
+ };
+
+ // Initialise the tracking system.
+ BOOST_ASIO_DECL static void init();
+
+ // Record the creation of a tracked handler.
+ BOOST_ASIO_DECL static void creation(tracked_handler* h,
+ const char* object_type, void* object, const char* op_name);
+
+ class completion
+ {
+ public:
+ // Constructor records that handler is to be invoked with no arguments.
+ BOOST_ASIO_DECL explicit completion(tracked_handler* h);
+
+ // Destructor records only when an exception is thrown from the handler, or
+ // if the memory is being freed without the handler having been invoked.
+ BOOST_ASIO_DECL ~completion();
+
+ // Records that handler is to be invoked with no arguments.
+ BOOST_ASIO_DECL void invocation_begin();
+
+ // Records that handler is to be invoked with one arguments.
+ BOOST_ASIO_DECL void invocation_begin(const boost::system::error_code& ec);
+
+ // Constructor records that handler is to be invoked with two arguments.
+ BOOST_ASIO_DECL void invocation_begin(
+ const boost::system::error_code& ec, std::size_t bytes_transferred);
+
+ // Constructor records that handler is to be invoked with two arguments.
+ BOOST_ASIO_DECL void invocation_begin(
+ const boost::system::error_code& ec, int signal_number);
+
+ // Constructor records that handler is to be invoked with two arguments.
+ BOOST_ASIO_DECL void invocation_begin(
+ const boost::system::error_code& ec, const char* arg);
+
+ // Record that handler invocation has ended.
+ BOOST_ASIO_DECL void invocation_end();
+
+ private:
+ friend class handler_tracking;
+ boost::uint64_t id_;
+ bool invoked_;
+ completion* next_;
+ };
+
+ // Record an operation that affects pending handlers.
+ BOOST_ASIO_DECL static void operation(const char* object_type,
+ void* object, const char* op_name);
+
+ // Write a line of output.
+ BOOST_ASIO_DECL static void write_line(const char* format, ...);
+
+private:
+ struct tracking_state;
+ BOOST_ASIO_DECL static tracking_state* get_state();
+};
+
+# define BOOST_ASIO_INHERIT_TRACKED_HANDLER \
+ : public boost::asio::detail::handler_tracking::tracked_handler
+
+# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER \
+ , public boost::asio::detail::handler_tracking::tracked_handler
+
+# define BOOST_ASIO_HANDLER_TRACKING_INIT \
+ boost::asio::detail::handler_tracking::init()
+
+# define BOOST_ASIO_HANDLER_CREATION(args) \
+ boost::asio::detail::handler_tracking::creation args
+
+# define BOOST_ASIO_HANDLER_COMPLETION(args) \
+ boost::asio::detail::handler_tracking::completion tracked_completion args
+
+# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) \
+ tracked_completion.invocation_begin args
+
+# define BOOST_ASIO_HANDLER_INVOCATION_END \
+ tracked_completion.invocation_end()
+
+# define BOOST_ASIO_HANDLER_OPERATION(args) \
+ boost::asio::detail::handler_tracking::operation args
+
+#else // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+# define BOOST_ASIO_INHERIT_TRACKED_HANDLER
+# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
+# define BOOST_ASIO_HANDLER_TRACKING_INIT (void)0
+# define BOOST_ASIO_HANDLER_CREATION(args) (void)0
+# define BOOST_ASIO_HANDLER_COMPLETION(args) (void)0
+# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0
+# define BOOST_ASIO_HANDLER_INVOCATION_END (void)0
+# define BOOST_ASIO_HANDLER_OPERATION(args) (void)0
+
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/handler_tracking.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TRACKING_HPP

Modified: trunk/boost/asio/detail/handler_type_requirements.hpp
==============================================================================
--- trunk/boost/asio/detail/handler_type_requirements.hpp (original)
+++ trunk/boost/asio/detail/handler_type_requirements.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -245,6 +245,26 @@
           boost::asio::detail::lvref<const boost::system::error_code>()), \
         char(0))>
 
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ static_cast<handler_type*>(0), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ handler_type( \
+ static_cast<const handler_type&>(handler))) + \
+ sizeof( \
+ handler( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))>
+
 #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
 
 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
@@ -279,6 +299,10 @@
     handler_type, handler) \
   typedef int
 
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int
+
 #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
 
 } // namespace detail

Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -75,6 +75,26 @@
   return 0;
 }
 
+int dev_poll_reactor::register_internal_descriptor(int op_type,
+ socket_type descriptor, per_descriptor_data&, reactor_op* op)
+{
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ op_queue_[op_type].enqueue_operation(descriptor, op);
+ ::pollfd& ev = add_pending_event_change(descriptor);
+ ev.events = POLLERR | POLLHUP;
+ switch (op_type)
+ {
+ case read_op: ev.events |= POLLIN; break;
+ case write_op: ev.events |= POLLOUT; break;
+ case except_op: ev.events |= POLLPRI; break;
+ default: break;
+ }
+ interrupter_.interrupt();
+
+ return 0;
+}
+
 void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
     dev_poll_reactor::per_descriptor_data&,
     reactor_op* op, bool allow_speculative)

Modified: trunk/boost/asio/detail/impl/epoll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -40,11 +40,7 @@
     io_service_(use_service<io_service_impl>(io_service)),
     mutex_(),
     epoll_fd_(do_epoll_create()),
-#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)
+ timer_fd_(do_timerfd_create()),
     interrupter_(),
     shutdown_(false)
 {
@@ -115,6 +111,35 @@
   return 0;
 }
 
+int epoll_reactor::register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op)
+{
+ mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+ descriptor_data = registered_descriptors_.alloc();
+ descriptor_data->shutdown_ = false;
+ descriptor_data->op_queue_[op_type].push(op);
+
+ lock.unlock();
+
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLERR | EPOLLHUP | EPOLLET;
+ switch (op_type)
+ {
+ case read_op: ev.events |= EPOLLIN; break;
+ case write_op: ev.events |= EPOLLOUT; break;
+ case except_op: ev.events |= EPOLLPRI; break;
+ default: break;
+ };
+ ev.data.ptr = descriptor_data;
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ return errno;
+
+ return 0;
+}
+
 void epoll_reactor::start_op(int op_type, socket_type descriptor,
     epoll_reactor::per_descriptor_data& descriptor_data,
     reactor_op* op, bool allow_speculative)
@@ -331,16 +356,53 @@
 
 int epoll_reactor::do_epoll_create()
 {
- int fd = epoll_create(epoll_size);
+#if defined(EPOLL_CLOEXEC)
+ int fd = epoll_create1(EPOLL_CLOEXEC);
+#else // defined(EPOLL_CLOEXEC)
+ int fd = -1;
+ errno = EINVAL;
+#endif // defined(EPOLL_CLOEXEC)
+
+ if (fd == -1 && errno == EINVAL)
+ {
+ fd = epoll_create(epoll_size);
+ if (fd != -1)
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
+
   if (fd == -1)
   {
     boost::system::error_code ec(errno,
         boost::asio::error::get_system_category());
     boost::asio::detail::throw_error(ec, "epoll");
   }
+
   return fd;
 }
 
+int epoll_reactor::do_timerfd_create()
+{
+#if defined(BOOST_ASIO_HAS_TIMERFD)
+# if defined(TFD_CLOEXEC)
+ int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+# else // defined(TFD_CLOEXEC)
+ int fd = -1;
+ errno = EINVAL;
+# endif // defined(TFD_CLOEXEC)
+
+ if (fd == -1 && errno == EINVAL)
+ {
+ fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd != -1)
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
+
+ return fd;
+#else // defined(BOOST_ASIO_HAS_TIMERFD)
+ return -1;
+#endif // defined(BOOST_ASIO_HAS_TIMERFD)
+}
+
 void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
 {
   mutex::scoped_lock lock(mutex_);

Modified: trunk/boost/asio/detail/impl/eventfd_select_interrupter.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/eventfd_select_interrupter.ipp (original)
+++ trunk/boost/asio/detail/impl/eventfd_select_interrupter.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -42,22 +42,41 @@
 {
 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
   write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
- write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
   if (read_descriptor_ != -1)
   {
     ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+ ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
   }
- else
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
+ write_descriptor_ = read_descriptor_ =
+ ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
+ errno = EINVAL;
+ write_descriptor_ = read_descriptor_ = -1;
+# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
+ if (read_descriptor_ == -1 && errno == EINVAL)
+ {
+ write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
+ if (read_descriptor_ != -1)
+ {
+ ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+ ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
+ }
+ }
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+
+ if (read_descriptor_ == -1)
   {
     int pipe_fds[2];
     if (pipe(pipe_fds) == 0)
     {
       read_descriptor_ = pipe_fds[0];
       ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+ ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
       write_descriptor_ = pipe_fds[1];
       ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+ ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);
     }
     else
     {

Added: trunk/boost/asio/detail/impl/handler_tracking.ipp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/impl/handler_tracking.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,315 @@
+//
+// detail/impl/handler_tracking.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_IMPL_HANDLER_TRACKING_IPP
+#define BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+#include <cstdarg>
+#include <cstdio>
+#include <boost/asio/detail/handler_tracking.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_WINDOWS)
+# include <unistd.h>
+#endif // !defined(BOOST_WINDOWS)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct handler_tracking::tracking_state
+{
+ static_mutex mutex_;
+ boost::uint64_t next_id_;
+ tss_ptr<completion>* current_completion_;
+};
+
+handler_tracking::tracking_state* handler_tracking::get_state()
+{
+ static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0 };
+ return &state;
+}
+
+void handler_tracking::init()
+{
+ static tracking_state* state = get_state();
+
+ state->mutex_.init();
+
+ static_mutex::scoped_lock lock(state->mutex_);
+ if (state->current_completion_ == 0)
+ state->current_completion_ = new tss_ptr<completion>;
+}
+
+void handler_tracking::creation(handler_tracking::tracked_handler* h,
+ const char* object_type, void* object, const char* op_name)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ static tracking_state* state = get_state();
+
+ static_mutex::scoped_lock lock(state->mutex_);
+ h->id_ = state->next_id_++;
+ lock.unlock();
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ boost::uint64_t current_id = 0;
+ if (completion* current_completion = *state->current_completion_)
+ current_id = current_completion->id_;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.20s\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.20s\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ current_id, h->id_, object_type, object, op_name);
+}
+
+handler_tracking::completion::completion(handler_tracking::tracked_handler* h)
+ : id_(h->id_),
+ invoked_(false),
+ next_(*get_state()->current_completion_)
+{
+ *get_state()->current_completion_ = this;
+}
+
+handler_tracking::completion::~completion()
+{
+ if (id_)
+ {
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|%c%I64u|\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|%c%llu|\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ invoked_ ? '!' : '~', id_);
+ }
+
+ *get_state()->current_completion_ = next_;
+}
+
+void handler_tracking::completion::invocation_begin()
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|>%I64u|\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|>%llu|\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000), id_);
+
+ invoked_ = true;
+}
+
+void handler_tracking::completion::invocation_begin(
+ const boost::system::error_code& ec)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ id_, ec.category().name(), ec.value());
+
+ invoked_ = true;
+}
+
+void handler_tracking::completion::invocation_begin(
+ const boost::system::error_code& ec, std::size_t bytes_transferred)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ id_, ec.category().name(), ec.value(),
+ static_cast<boost::uint64_t>(bytes_transferred));
+
+ invoked_ = true;
+}
+
+void handler_tracking::completion::invocation_begin(
+ const boost::system::error_code& ec, int signal_number)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ id_, ec.category().name(), ec.value(), signal_number);
+
+ invoked_ = true;
+}
+
+void handler_tracking::completion::invocation_begin(
+ const boost::system::error_code& ec, const char* arg)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.20s\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.20s\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ id_, ec.category().name(), ec.value(), arg);
+
+ invoked_ = true;
+}
+
+void handler_tracking::completion::invocation_end()
+{
+ if (id_)
+ {
+ using namespace std; // For sprintf (or equivalent).
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|<%I64u|\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|<%llu|\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000), id_);
+
+ id_ = 0;
+ }
+}
+
+void handler_tracking::operation(const char* object_type,
+ void* object, const char* op_name)
+{
+ using namespace std; // For sprintf (or equivalent).
+
+ static tracking_state* state = get_state();
+
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ boost::posix_time::time_duration now =
+ boost::posix_time::microsec_clock::universal_time() - epoch;
+
+ unsigned long long current_id = 0;
+ if (completion* current_completion = *state->current_completion_)
+ current_id = current_completion->id_;
+
+ write_line(
+#if defined(BOOST_WINDOWS)
+ "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.20s\n",
+#else // defined(BOOST_WINDOWS)
+ "@asio|%llu.%06llu|%llu|%.20s@%p.%.20s\n",
+#endif // defined(BOOST_WINDOWS)
+ static_cast<boost::uint64_t>(now.total_seconds()),
+ static_cast<boost::uint64_t>(now.total_microseconds() % 1000000),
+ current_id, object_type, object, op_name);
+}
+
+void handler_tracking::write_line(const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ char line[256] = "";
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ int length = vsprintf_s(line, sizeof(line), format, args);
+#else // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ int length = vsprintf(line, format, args);
+#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+
+ va_end(args);
+
+#if defined(BOOST_WINDOWS)
+ HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
+ DWORD bytes_written = 0;
+ ::WriteFile(stderr_handle, line, length, &bytes_written, 0);
+#else // defined(BOOST_WINDOWS)
+ ::write(STDERR_FILENO, line, length);
+#endif // defined(BOOST_WINDOWS)
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP

Modified: trunk/boost/asio/detail/impl/kqueue_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -93,6 +93,37 @@
   return 0;
 }
 
+int kqueue_reactor::register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op)
+{
+ mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+ descriptor_data = registered_descriptors_.alloc();
+ descriptor_data->shutdown_ = false;
+ descriptor_data->op_queue_[op_type].push(op);
+
+ struct kevent event;
+ switch (op_type)
+ {
+ case read_op:
+ BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+ EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+ break;
+ case write_op:
+ BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
+ EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+ break;
+ case except_op:
+ BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+ EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+ break;
+ }
+ ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
+
+ return 0;
+}
+
 void kqueue_reactor::start_op(int op_type, socket_type descriptor,
     kqueue_reactor::per_descriptor_data& descriptor_data,
     reactor_op* op, bool allow_speculative)
@@ -314,12 +345,14 @@
               EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
         else
           continue;
+ break;
       case EVFILT_WRITE:
         if (!descriptor_data->op_queue_[write_op].empty())
           BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
               EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
         else
           continue;
+ break;
       default:
         break;
       }

Modified: trunk/boost/asio/detail/impl/pipe_select_interrupter.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/pipe_select_interrupter.ipp (original)
+++ trunk/boost/asio/detail/impl/pipe_select_interrupter.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -45,6 +45,11 @@
     ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
     write_descriptor_ = pipe_fds[1];
     ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+
+#if defined(FD_CLOEXEC)
+ ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
+ ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);
+#endif // defined(FD_CLOEXEC)
   }
   else
   {

Modified: trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp (original)
+++ trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -51,6 +51,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
+
     reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
         (impl.state_ & descriptor_ops::possible_dup) == 0);
   }
@@ -89,6 +91,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
+
     reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
         (impl.state_ & descriptor_ops::possible_dup) == 0);
   }
@@ -107,6 +111,8 @@
 
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release"));
+
     reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false);
     construct(impl);
   }
@@ -124,6 +130,8 @@
     return ec;
   }
 
+ BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "cancel"));
+
   reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
   ec = boost::system::error_code();
   return ec;

Modified: trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -50,6 +50,8 @@
 {
   if (impl.socket_ != invalid_socket)
   {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
     reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
         (impl.state_ & socket_ops::possible_dup) == 0);
 
@@ -64,6 +66,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
     reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
         (impl.state_ & socket_ops::possible_dup) == 0);
   }
@@ -84,6 +88,8 @@
     return ec;
   }
 
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+
   reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
   ec = boost::system::error_code();
   return ec;

Modified: trunk/boost/asio/detail/impl/resolver_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/resolver_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/resolver_service_base.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -72,13 +72,18 @@
 }
 
 void resolver_service_base::destroy(
- resolver_service_base::implementation_type&)
+ resolver_service_base::implementation_type& impl)
 {
+ BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel"));
+
+ impl.reset();
 }
 
 void resolver_service_base::cancel(
     resolver_service_base::implementation_type& impl)
 {
+ BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel"));
+
   impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
 }
 

Modified: trunk/boost/asio/detail/impl/select_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -95,6 +95,18 @@
   return 0;
 }
 
+int select_reactor::register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ select_reactor::per_descriptor_data&, reactor_op* op)
+{
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ op_queue_[op_type].enqueue_operation(descriptor, op);
+ interrupter_.interrupt();
+
+ return 0;
+}
+
 void select_reactor::start_op(int op_type, socket_type descriptor,
     select_reactor::per_descriptor_data&, reactor_op* op, bool)
 {

Added: trunk/boost/asio/detail/impl/signal_set_service.ipp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/impl/signal_set_service.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,518 @@
+//
+// detail/impl/signal_set_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_IMPL_SIGNAL_SET_SERVICE_IPP
+#define BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <signal.h>
+#include <cstring>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/signal_set_service.hpp>
+#include <boost/asio/detail/static_mutex.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct signal_state
+{
+ // Mutex used for protecting global state.
+ static_mutex mutex_;
+
+ // The read end of the pipe used for signal notifications.
+ int read_descriptor_;
+
+ // The write end of the pipe used for signal notifications.
+ int write_descriptor_;
+
+ // The head of a linked list of all signal_set_service instances.
+ class signal_set_service* service_list_;
+
+ // A count of the number of objects that are registered for each signal.
+ std::size_t registration_count_[max_signal_number];
+};
+
+signal_state* get_signal_state()
+{
+ static signal_state state = {
+ BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, 0, { 0 } };
+ return &state;
+}
+
+void asio_signal_handler(int signal_number)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ signal_set_service::deliver_signal(signal_number);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ signal_state* state = get_signal_state();
+ (void)::write(state->write_descriptor_,
+ &signal_number, sizeof(signal_number));
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if !defined(BOOST_ASIO_HAS_SIGACTION)
+ signal(signal_number, asio_signal_handler);
+#endif // !defined(BOOST_ASIO_HAS_SIGACTION)
+}
+
+signal_set_service::signal_set_service(
+ boost::asio::io_service& io_service)
+ : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ reactor_(boost::asio::use_service<reactor>(io_service)),
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ next_(0),
+ prev_(0)
+{
+ get_signal_state()->mutex_.init();
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ reactor_.init_task();
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+ for (int i = 0; i < max_signal_number; ++i)
+ registrations_[i] = 0;
+
+ add_service(this);
+}
+
+signal_set_service::~signal_set_service()
+{
+ remove_service(this);
+}
+
+void signal_set_service::shutdown_service()
+{
+ remove_service(this);
+
+ op_queue<operation> ops;
+
+ for (int i = 0; i < max_signal_number; ++i)
+ {
+ registration* reg = registrations_[i];
+ while (reg)
+ {
+ ops.push(*reg->queue_);
+ reg = reg->next_in_table_;
+ }
+ }
+}
+
+void signal_set_service::construct(
+ signal_set_service::implementation_type& impl)
+{
+ impl.signals_ = 0;
+}
+
+void signal_set_service::destroy(
+ signal_set_service::implementation_type& impl)
+{
+ boost::system::error_code ignored_ec;
+ clear(impl, ignored_ec);
+ cancel(impl, ignored_ec);
+}
+
+boost::system::error_code signal_set_service::add(
+ signal_set_service::implementation_type& impl,
+ int signal_number, boost::system::error_code& ec)
+{
+ // Check that the signal number is valid.
+ if (signal_number < 0 || signal_number > max_signal_number)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ // Find the appropriate place to insert the registration.
+ registration** insertion_point = &impl.signals_;
+ registration* next = impl.signals_;
+ while (next && next->signal_number_ < signal_number)
+ {
+ insertion_point = &next->next_in_set_;
+ next = next->next_in_set_;
+ }
+
+ // Only do something if the signal is not already registered.
+ if (next == 0 || next->signal_number_ != signal_number)
+ {
+ registration* new_registration = new registration;
+
+ // Register for the signal if we're the first.
+ if (state->registration_count_[signal_number] == 0)
+ {
+#if defined(BOOST_ASIO_HAS_SIGACTION)
+ using namespace std; // For memset.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = asio_signal_handler;
+ sigfillset(&sa.sa_mask);
+ if (::sigaction(signal_number, &sa, 0) == -1)
+#else // defined(BOOST_ASIO_HAS_SIGACTION)
+ if (::signal(signal_number, asio_signal_handler) == SIG_ERR)
+#endif // defined(BOOST_ASIO_HAS_SIGACTION)
+ {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::asio::error::invalid_argument;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ delete new_registration;
+ return ec;
+ }
+ }
+
+ // Record the new registration in the set.
+ new_registration->signal_number_ = signal_number;
+ new_registration->queue_ = &impl.queue_;
+ new_registration->next_in_set_ = next;
+ *insertion_point = new_registration;
+
+ // Insert registration into the registration table.
+ new_registration->next_in_table_ = registrations_[signal_number];
+ if (registrations_[signal_number])
+ registrations_[signal_number]->prev_in_table_ = new_registration;
+ registrations_[signal_number] = new_registration;
+
+ ++state->registration_count_[signal_number];
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code signal_set_service::remove(
+ signal_set_service::implementation_type& impl,
+ int signal_number, boost::system::error_code& ec)
+{
+ // Check that the signal number is valid.
+ if (signal_number < 0 || signal_number > max_signal_number)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ // Find the signal number in the list of registrations.
+ registration** deletion_point = &impl.signals_;
+ registration* reg = impl.signals_;
+ while (reg && reg->signal_number_ < signal_number)
+ {
+ deletion_point = &reg->next_in_set_;
+ reg = reg->next_in_set_;
+ }
+
+ if (reg != 0 && reg->signal_number_ == signal_number)
+ {
+ // Set signal handler back to the default if we're the last.
+ if (state->registration_count_[signal_number] == 1)
+ {
+#if defined(BOOST_ASIO_HAS_SIGACTION)
+ using namespace std; // For memset.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ if (::sigaction(signal_number, &sa, 0) == -1)
+#else // defined(BOOST_ASIO_HAS_SIGACTION)
+ if (::signal(signal_number, SIG_DFL) == SIG_ERR)
+#endif // defined(BOOST_ASIO_HAS_SIGACTION)
+ {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::asio::error::invalid_argument;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return ec;
+ }
+ }
+
+ // Remove the registration from the set.
+ *deletion_point = reg->next_in_set_;
+
+ // Remove the registration from the registration table.
+ if (registrations_[signal_number] == reg)
+ registrations_[signal_number] = reg->next_in_table_;
+ if (reg->prev_in_table_)
+ reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
+ if (reg->next_in_table_)
+ reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
+
+ --state->registration_count_[signal_number];
+
+ delete reg;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code signal_set_service::clear(
+ signal_set_service::implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ while (registration* reg = impl.signals_)
+ {
+ // Set signal handler back to the default if we're the last.
+ if (state->registration_count_[reg->signal_number_] == 1)
+ {
+#if defined(BOOST_ASIO_HAS_SIGACTION)
+ using namespace std; // For memset.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ if (::sigaction(reg->signal_number_, &sa, 0) == -1)
+#else // defined(BOOST_ASIO_HAS_SIGACTION)
+ if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR)
+#endif // defined(BOOST_ASIO_HAS_SIGACTION)
+ {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::asio::error::invalid_argument;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return ec;
+ }
+ }
+
+ // Remove the registration from the registration table.
+ if (registrations_[reg->signal_number_] == reg)
+ registrations_[reg->signal_number_] = reg->next_in_table_;
+ if (reg->prev_in_table_)
+ reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
+ if (reg->next_in_table_)
+ reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
+
+ --state->registration_count_[reg->signal_number_];
+
+ impl.signals_ = reg->next_in_set_;
+ delete reg;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code signal_set_service::cancel(
+ signal_set_service::implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ BOOST_ASIO_HANDLER_OPERATION(("signal_set", &impl, "cancel"));
+
+ op_queue<operation> ops;
+ while (signal_op* op = impl.queue_.front())
+ {
+ op->ec_ = boost::asio::error::operation_aborted;
+ impl.queue_.pop();
+ ops.push(op);
+ }
+
+ io_service_.post_deferred_completions(ops);
+
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void signal_set_service::deliver_signal(int signal_number)
+{
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ signal_set_service* service = state->service_list_;
+ while (service)
+ {
+ op_queue<operation> ops;
+
+ registration* reg = service->registrations_[signal_number];
+ while (reg)
+ {
+ if (reg->queue_->empty())
+ {
+ ++reg->undelivered_;
+ }
+ else
+ {
+ while (signal_op* op = reg->queue_->front())
+ {
+ op->signal_number_ = signal_number;
+ reg->queue_->pop();
+ ops.push(op);
+ }
+ }
+
+ reg = reg->next_in_table_;
+ }
+
+ service->io_service_.post_deferred_completions(ops);
+
+ service = service->next_;
+ }
+}
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+class signal_set_service::pipe_read_op : public reactor_op
+{
+public:
+ pipe_read_op()
+ : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
+ {
+ }
+
+ static bool do_perform(reactor_op*)
+ {
+ signal_state* state = get_signal_state();
+
+ int fd = state->read_descriptor_;
+ int signal_number = 0;
+ while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
+ if (signal_number >= 0 && signal_number < max_signal_number)
+ signal_set_service::deliver_signal(signal_number);
+
+ return false;
+ }
+
+ static void do_complete(io_service_impl* /*owner*/, operation* base,
+ boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ pipe_read_op* o(static_cast<pipe_read_op*>(base));
+ delete o;
+ }
+};
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+void signal_set_service::add_service(signal_set_service* service)
+{
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ // If this is the first service to be created, open a new pipe.
+ if (state->service_list_ == 0)
+ {
+ int pipe_fds[2];
+ if (::pipe(pipe_fds) == 0)
+ {
+ state->read_descriptor_ = pipe_fds[0];
+ ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
+
+ state->write_descriptor_ = pipe_fds[1];
+ ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
+
+#if defined(FD_CLOEXEC)
+ ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
+ ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
+#endif // defined(FD_CLOEXEC)
+ }
+ else
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ boost::asio::detail::throw_error(ec, "signal_set_service pipe");
+ }
+ }
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+ // Insert service into linked list of all services.
+ service->next_ = state->service_list_;
+ service->prev_ = 0;
+ if (state->service_list_)
+ state->service_list_->prev_ = service;
+ state->service_list_ = service;
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ // Register for pipe readiness notifications.
+ service->reactor_.register_internal_descriptor(reactor::read_op,
+ state->read_descriptor_, service->reactor_data_, new pipe_read_op);
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+}
+
+void signal_set_service::remove_service(signal_set_service* service)
+{
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ if (service->next_ || service->prev_ || state->service_list_ == service)
+ {
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ // Disable the pipe readiness notifications.
+ service->reactor_.deregister_descriptor(
+ state->read_descriptor_, service->reactor_data_, false);
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+ // Remove service from linked list of all services.
+ if (state->service_list_ == service)
+ state->service_list_ = service->next_;
+ if (service->prev_)
+ service->prev_->next_ = service->next_;
+ if (service->next_)
+ service->next_->prev_= service->prev_;
+ service->next_ = 0;
+ service->prev_ = 0;
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ // If this is the last service to be removed, close the pipe.
+ if (state->service_list_ == 0)
+ {
+ ::close(state->read_descriptor_);
+ state->read_descriptor_ = -1;
+ ::close(state->write_descriptor_);
+ state->write_descriptor_ = -1;
+ }
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ }
+}
+
+void signal_set_service::start_wait_op(
+ signal_set_service::implementation_type& impl, signal_op* op)
+{
+ io_service_.work_started();
+
+ signal_state* state = get_signal_state();
+ static_mutex::scoped_lock lock(state->mutex_);
+
+ registration* reg = impl.signals_;
+ while (reg)
+ {
+ if (reg->undelivered_ > 0)
+ {
+ --reg->undelivered_;
+ io_service_.post_deferred_completion(op);
+ return;
+ }
+
+ reg = reg->next_in_set_;
+ }
+
+ impl.queue_.push(op);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP

Modified: trunk/boost/asio/detail/impl/strand_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/strand_service.hpp (original)
+++ trunk/boost/asio/detail/impl/strand_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -98,6 +98,8 @@
     return;
   }
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "dispatch"));
+
   // Immediate invocation is not allowed, so enqueue for later.
   impl->queue_.push(p.p);
   impl->mutex_.unlock();
@@ -121,6 +123,8 @@
       sizeof(op), handler), 0 };
   p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "post"));
+
   // Add the handler to the queue.
   impl->mutex_.lock();
   bool first = (++impl->count_ == 1);

Modified: trunk/boost/asio/detail/impl/task_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/task_io_service.hpp (original)
+++ trunk/boost/asio/detail/impl/task_io_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -36,7 +36,19 @@
     boost_asio_handler_invoke_helpers::invoke(handler, handler);
   }
   else
- post(handler);
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef completion_handler<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
+
+ post_immediate_completion(p.p);
+ p.v = p.p = 0;
+ }
 }
 
 template <typename Handler>
@@ -49,6 +61,8 @@
       sizeof(op), handler), 0 };
   p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
+
   post_immediate_completion(p.p);
   p.v = p.p = 0;
 }

Modified: trunk/boost/asio/detail/impl/task_io_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/task_io_service.ipp (original)
+++ trunk/boost/asio/detail/impl/task_io_service.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -74,6 +74,7 @@
     shutdown_(false),
     first_idle_thread_(0)
 {
+ BOOST_ASIO_HANDLER_TRACKING_INIT;
 }
 
 void task_io_service::init(std::size_t /*concurrency_hint*/)

Modified: trunk/boost/asio/detail/impl/win_iocp_handle_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_handle_service.ipp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_handle_service.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -141,6 +141,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "close"));
+
     if (!::CloseHandle(impl.handle_))
     {
       DWORD last_error = ::GetLastError();
@@ -164,8 +166,12 @@
   if (!is_open(impl))
   {
     ec = boost::asio::error::bad_descriptor;
+ return ec;
   }
- else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+
+ BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "cancel"));
+
+ if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
         ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
   {
     // The version of Windows supports cancellation from any thread.
@@ -437,6 +443,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "close"));
+
     ::CloseHandle(impl.handle_);
     impl.handle_ = INVALID_HANDLE_VALUE;
     impl.safe_cancellation_thread_id_ = 0;

Modified: trunk/boost/asio/detail/impl/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_io_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -40,7 +40,19 @@
     boost_asio_handler_invoke_helpers::invoke(handler, handler);
   }
   else
- post(handler);
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef completion_handler<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
+
+ post_immediate_completion(p.p);
+ p.v = p.p = 0;
+ }
 }
 
 template <typename Handler>
@@ -53,6 +65,8 @@
       sizeof(op), handler), 0 };
   p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
+
   post_immediate_completion(p.p);
   p.v = p.p = 0;
 }

Modified: trunk/boost/asio/detail/impl/win_iocp_io_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_io_service.ipp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_io_service.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -70,6 +70,7 @@
     shutdown_(0),
     dispatch_required_(0)
 {
+ BOOST_ASIO_HANDLER_TRACKING_INIT;
 }
 
 void win_iocp_io_service::init(size_t concurrency_hint)

Modified: trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -92,6 +92,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
     // 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.
@@ -124,7 +126,10 @@
     ec = boost::asio::error::bad_descriptor;
     return ec;
   }
- else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+
+ if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
         ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
   {
     // The version of Windows supports cancellation from any thread.
@@ -497,6 +502,8 @@
 {
   if (is_open(impl))
   {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
     // 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.

Added: trunk/boost/asio/detail/impl/win_static_mutex.ipp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/impl/win_static_mutex.ipp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,120 @@
+//
+// detail/impl/win_static_mutex.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_IMPL_WIN_STATIC_MUTEX_IPP
+#define BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#include <cstdio>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/win_static_mutex.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+void win_static_mutex::init()
+{
+ int error = do_init();
+ boost::system::error_code ec(error,
+ boost::asio::error::get_system_category());
+ boost::asio::detail::throw_error(ec, "static_mutex");
+}
+
+int win_static_mutex::do_init()
+{
+ using namespace std; // For sprintf.
+ wchar_t mutex_name[128];
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ swprintf_s(mutex_name, 128,
+#else // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ swprintf(mutex_name,
+#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p",
+ static_cast<unsigned int>(::GetCurrentProcessId()), this);
+
+ HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name);
+ DWORD last_error = ::GetLastError();
+ if (mutex == 0)
+ return ::GetLastError();
+
+ if (last_error == ERROR_ALREADY_EXISTS)
+ ::WaitForSingleObject(mutex, INFINITE);
+
+ if (initialised_)
+ {
+ ::ReleaseMutex(mutex);
+ ::CloseHandle(mutex);
+ return 0;
+ }
+
+#if defined(__MINGW32__)
+ // Not sure if MinGW supports structured exception handling, so for now
+ // we'll just call the Windows API and hope.
+# if defined(UNDER_CE)
+ ::InitializeCriticalSection(&crit_section_);
+# else
+ if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+ {
+ last_error = ::GetLastError();
+ ::ReleaseMutex(mutex);
+ ::CloseHandle(mutex);
+ return last_error;
+ }
+# endif
+#else
+ __try
+ {
+# if defined(UNDER_CE)
+ ::InitializeCriticalSection(&crit_section_);
+# else
+ if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+ {
+ last_error = ::GetLastError();
+ ::ReleaseMutex(mutex);
+ ::CloseHandle(mutex);
+ return last_error;
+ }
+# endif
+ }
+ __except(GetExceptionCode() == STATUS_NO_MEMORY
+ ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ ::ReleaseMutex(mutex);
+ ::CloseHandle(mutex);
+ return ERROR_OUTOFMEMORY;
+ }
+#endif
+
+ initialised_ = true;
+ ::ReleaseMutex(mutex);
+ ::CloseHandle(mutex);
+ return 0;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP

Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -89,6 +89,12 @@
   BOOST_ASIO_DECL int register_descriptor(socket_type descriptor,
       per_descriptor_data& descriptor_data);
 
+ // Register a descriptor with an associated single operation. Returns 0 on
+ // success, system error code on failure.
+ BOOST_ASIO_DECL int register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ per_descriptor_data& descriptor_data, reactor_op* op);
+
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op)
   {

Added: trunk/boost/asio/detail/null_static_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/null_static_mutex.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,62 @@
+//
+// detail/null_static_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_NULL_STATIC_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_NULL_STATIC_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
+
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct null_static_mutex
+{
+ typedef boost::asio::detail::scoped_lock<null_static_mutex> scoped_lock;
+
+ // Initialise the mutex.
+ void init()
+ {
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ }
+
+ int unused_;
+};
+
+#define BOOST_ASIO_NULL_STATIC_MUTEX_INIT { 0 }
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
+
+#endif // BOOST_ASIO_DETAIL_NULL_STATIC_MUTEX_HPP

Added: trunk/boost/asio/detail/posix_static_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/posix_static_mutex.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,66 @@
+//
+// detail/posix_static_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_POSIX_STATIC_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_POSIX_STATIC_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+
+#include <pthread.h>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct posix_static_mutex
+{
+ typedef boost::asio::detail::scoped_lock<posix_static_mutex> scoped_lock;
+
+ // Initialise the mutex.
+ void init()
+ {
+ // Nothing to do.
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.
+ }
+
+ ::pthread_mutex_t mutex_;
+};
+
+#define BOOST_ASIO_POSIX_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER }
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+
+#endif // BOOST_ASIO_DETAIL_POSIX_STATIC_MUTEX_HPP

Modified: trunk/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_descriptor_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_descriptor_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -186,6 +186,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.descriptor_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_write_some"));
+
     start_op(impl, reactor::write_op, p.p, true,
         buffer_sequence_adapter<boost::asio::const_buffer,
           ConstBufferSequence>::all_empty(buffers));
@@ -204,6 +206,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
+ &impl, "async_write_some(null_buffers)"));
+
     start_op(impl, reactor::write_op, p.p, false, false);
     p.v = p.p = 0;
   }
@@ -243,6 +248,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.descriptor_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_read_some"));
+
     start_op(impl, reactor::read_op, p.p, true,
         buffer_sequence_adapter<boost::asio::mutable_buffer,
           MutableBufferSequence>::all_empty(buffers));
@@ -261,6 +268,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
+ &impl, "async_read_some(null_buffers)"));
+
     start_op(impl, reactor::read_op, p.p, false, false);
     p.v = p.p = 0;
   }

Modified: trunk/boost/asio/detail/reactive_null_buffers_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_null_buffers_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_null_buffers_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -53,6 +53,8 @@
     reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -68,7 +70,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_accept_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_accept_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_accept_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -101,6 +101,8 @@
     reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -116,7 +118,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_connect_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_connect_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_connect_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -71,6 +71,8 @@
       (static_cast<reactive_socket_connect_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -86,7 +88,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_recv_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_recv_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_recv_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -54,7 +54,7 @@
 
     return socket_ops::non_blocking_recv(o->socket_,
         bufs.buffers(), bufs.count(), o->flags_,
- (o->state_ & socket_ops::stream_oriented),
+ (o->state_ & socket_ops::stream_oriented) != 0,
         o->ec_, o->bytes_transferred_);
   }
 
@@ -88,6 +88,8 @@
     reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -103,7 +105,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_recvfrom_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_recvfrom_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_recvfrom_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -98,6 +98,8 @@
         static_cast<reactive_socket_recvfrom_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -113,7 +115,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_recvmsg_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_recvmsg_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_recvmsg_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -90,6 +90,8 @@
         static_cast<reactive_socket_recvmsg_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -105,7 +107,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_send_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_send_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_send_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -85,6 +85,8 @@
     reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -100,7 +102,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_sendto_op.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_sendto_op.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_sendto_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -88,6 +88,8 @@
     reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -103,7 +105,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -204,6 +204,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+
     start_op(impl, reactor::write_op, p.p, true, false);
     p.v = p.p = 0;
   }
@@ -220,6 +222,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send_to(null_buffers)"));
+
     start_op(impl, reactor::write_op, p.p, false, false);
     p.v = p.p = 0;
   }
@@ -278,6 +283,9 @@
     p.p = new (p.v) op(impl.socket_, protocol,
         buffers, sender_endpoint, flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from"));
+
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
@@ -298,6 +306,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from(null_buffers)"));
+
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
 
@@ -351,6 +362,8 @@
     p.p = new (p.v) op(impl.socket_, impl.state_, peer,
         impl.protocol_, peer_endpoint, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+
     start_accept_op(impl, p.p, peer.is_open());
     p.v = p.p = 0;
   }
@@ -376,6 +389,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+
     start_connect_op(impl, p.p, peer_endpoint.data(), peer_endpoint.size());
     p.v = p.p = 0;
   }

Modified: trunk/boost/asio/detail/reactive_socket_service_base.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service_base.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service_base.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -198,6 +198,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+
     start_op(impl, reactor::write_op, p.p, true,
         ((impl.state_ & socket_ops::stream_oriented)
           && buffer_sequence_adapter<boost::asio::const_buffer,
@@ -217,6 +219,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send(null_buffers)"));
+
     start_op(impl, reactor::write_op, p.p, false, false);
     p.v = p.p = 0;
   }
@@ -258,6 +263,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
@@ -280,6 +287,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive(null_buffers)"));
+
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
@@ -331,6 +341,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_with_flags"));
+
     start_op(impl,
         (in_flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
@@ -351,6 +364,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_with_flags(null_buffers)"));
+
     // Clear out_flags, since we cannot give it any other sensible value when
     // performing a null_buffers operation.
     out_flags = 0;

Modified: trunk/boost/asio/detail/resolve_endpoint_op.hpp
==============================================================================
--- trunk/boost/asio/detail/resolve_endpoint_op.hpp (original)
+++ trunk/boost/asio/detail/resolve_endpoint_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -81,6 +81,8 @@
       // The operation has been returned to the main io_service. The completion
       // handler is ready to be delivered.
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
       // 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
@@ -95,7 +97,9 @@
       if (owner)
       {
         boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
         boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
       }
     }
   }

Modified: trunk/boost/asio/detail/resolve_op.hpp
==============================================================================
--- trunk/boost/asio/detail/resolve_op.hpp (original)
+++ trunk/boost/asio/detail/resolve_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -86,6 +86,8 @@
       // The operation has been returned to the main io_service. The completion
       // handler is ready to be delivered.
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
       // 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
@@ -105,7 +107,9 @@
       if (owner)
       {
         boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
         boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
       }
     }
   }

Modified: trunk/boost/asio/detail/resolver_service.hpp
==============================================================================
--- trunk/boost/asio/detail/resolver_service.hpp (original)
+++ trunk/boost/asio/detail/resolver_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -77,6 +77,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl, query, io_service_impl_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));
+
     start_resolve_op(p.p);
     p.v = p.p = 0;
   }
@@ -107,6 +109,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl, endpoint, io_service_impl_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));
+
     start_resolve_op(p.p);
     p.v = p.p = 0;
   }

Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -80,6 +80,12 @@
   // code on failure.
   BOOST_ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
 
+ // Register a descriptor with an associated single operation. Returns 0 on
+ // success, system error code on failure.
+ BOOST_ASIO_DECL int register_internal_descriptor(
+ int op_type, socket_type descriptor,
+ per_descriptor_data& descriptor_data, reactor_op* op);
+
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op)
   {

Added: trunk/boost/asio/detail/signal_handler.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/signal_handler.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,82 @@
+//
+// detail/signal_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_SIGNAL_HANDLER_HPP
+#define BOOST_ASIO_DETAIL_SIGNAL_HANDLER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.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/signal_op.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class signal_handler : public signal_op
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(signal_handler);
+
+ signal_handler(Handler h)
+ : signal_op(&signal_handler::do_complete),
+ handler_(h)
+ {
+ }
+
+ 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.
+ signal_handler* h(static_cast<signal_handler*>(base));
+ ptr p = { boost::addressof(h->handler_), h, h };
+
+ BOOST_ASIO_HANDLER_COMPLETION((h));
+
+ // 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, int>
+ handler(h->handler_, h->ec_, h->signal_number_);
+ p.h = boost::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SIGNAL_HANDLER_HPP

Added: trunk/boost/asio/detail/signal_op.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/signal_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,51 @@
+//
+// detail/signal_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_SIGNAL_OP_HPP
+#define BOOST_ASIO_DETAIL_SIGNAL_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/operation.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class signal_op
+ : public operation
+{
+public:
+ // The error code to be passed to the completion handler.
+ boost::system::error_code ec_;
+
+ // The signal number to be passed to the completion handler.
+ int signal_number_;
+
+protected:
+ signal_op(func_type func)
+ : operation(func),
+ signal_number_(0)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SIGNAL_OP_HPP

Added: trunk/boost/asio/detail/signal_set_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/signal_set_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,204 @@
+//
+// detail/signal_set_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_SIGNAL_SET_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <cstddef>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/signal_handler.hpp>
+#include <boost/asio/detail/signal_op.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# include <boost/asio/detail/reactor.hpp>
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(NSIG) && (NSIG > 0)
+enum { max_signal_number = NSIG };
+#elif defined(SIGRTMAX)
+enum { max_signal_number = SIGRTMAX + 1 };
+#else
+enum { max_signal_number = 128 };
+#endif
+
+extern BOOST_ASIO_DECL struct signal_state* get_signal_state();
+
+extern "C" BOOST_ASIO_DECL void asio_signal_handler(int signal_number);
+
+class signal_set_service
+{
+public:
+ // Type used for tracking an individual signal registration.
+ class registration
+ {
+ public:
+ // Default constructor.
+ registration()
+ : signal_number_(0),
+ queue_(0),
+ undelivered_(0),
+ next_in_table_(0),
+ prev_in_table_(0),
+ next_in_set_(0)
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class signal_set_service;
+
+ // The signal number that is registered.
+ int signal_number_;
+
+ // The waiting signal handlers.
+ op_queue<signal_op>* queue_;
+
+ // The number of undelivered signals.
+ std::size_t undelivered_;
+
+ // Pointers to adjacent registrations in the registrations_ table.
+ registration* next_in_table_;
+ registration* prev_in_table_;
+
+ // Link to next registration in the signal set.
+ registration* next_in_set_;
+ };
+
+ // The implementation type of the signal_set.
+ class implementation_type
+ {
+ public:
+ // Default constructor.
+ implementation_type()
+ : signals_(0)
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class signal_set_service;
+
+ // The pending signal handlers.
+ op_queue<signal_op> queue_;
+
+ // Linked list of registered signals.
+ registration* signals_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL signal_set_service(boost::asio::io_service& io_service);
+
+ // Destructor.
+ BOOST_ASIO_DECL ~signal_set_service();
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void shutdown_service();
+
+ // Construct a new signal_set implementation.
+ BOOST_ASIO_DECL void construct(implementation_type& impl);
+
+ // Destroy a signal_set implementation.
+ BOOST_ASIO_DECL void destroy(implementation_type& impl);
+
+ // Add a signal to a signal_set.
+ BOOST_ASIO_DECL boost::system::error_code add(implementation_type& impl,
+ int signal_number, boost::system::error_code& ec);
+
+ // Remove a signal to a signal_set.
+ BOOST_ASIO_DECL boost::system::error_code remove(implementation_type& impl,
+ int signal_number, boost::system::error_code& ec);
+
+ // Remove all signals from a signal_set.
+ BOOST_ASIO_DECL boost::system::error_code clear(implementation_type& impl,
+ boost::system::error_code& ec);
+
+ // Cancel all operations associated with the signal set.
+ BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec);
+
+ // Start an asynchronous operation to wait for a signal to be delivered.
+ template <typename Handler>
+ void async_wait(implementation_type& impl, Handler& handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef signal_handler<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "signal_set", &impl, "async_wait"));
+
+ start_wait_op(impl, p.p);
+ p.v = p.p = 0;
+ }
+
+ // Deliver notification that a particular signal occurred.
+ BOOST_ASIO_DECL static void deliver_signal(int signal_number);
+
+private:
+ // Helper function to add a service to the global signal state.
+ BOOST_ASIO_DECL static void add_service(signal_set_service* service);
+
+ // Helper function to remove a service from the global signal state.
+ BOOST_ASIO_DECL static void remove_service(signal_set_service* service);
+
+ // Helper function to start a wait operation.
+ BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op);
+
+ // The io_service instance used for dispatching handlers.
+ io_service_impl& io_service_;
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ // The type used for registering for pipe reactor notifications.
+ class pipe_read_op;
+
+ // The reactor used for waiting for pipe readiness.
+ reactor& reactor_;
+
+ // The per-descriptor reactor data used for the pipe.
+ reactor::per_descriptor_data reactor_data_;
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+ // A mapping from signal number to the registered signal sets.
+ registration* registrations_[max_signal_number];
+
+ // Pointers to adjacent services in linked list.
+ signal_set_service* next_;
+ signal_set_service* prev_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/signal_set_service.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP

Added: trunk/boost/asio/detail/static_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/static_mutex.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,49 @@
+//
+// detail/static_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_STATIC_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_STATIC_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
+# include <boost/asio/detail/null_static_mutex.hpp>
+#elif defined(BOOST_WINDOWS)
+# include <boost/asio/detail/win_static_mutex.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_static_mutex.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
+typedef null_static_mutex static_mutex;
+# define BOOST_ASIO_STATIC_MUTEX_INIT BOOST_ASIO_NULL_STATIC_MUTEX_INIT
+#elif defined(BOOST_WINDOWS)
+typedef win_static_mutex static_mutex;
+# define BOOST_ASIO_STATIC_MUTEX_INIT BOOST_ASIO_WIN_STATIC_MUTEX_INIT
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_static_mutex static_mutex;
+# define BOOST_ASIO_STATIC_MUTEX_INIT BOOST_ASIO_POSIX_STATIC_MUTEX_INIT
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_STATIC_MUTEX_HPP

Modified: trunk/boost/asio/detail/task_io_service_operation.hpp
==============================================================================
--- trunk/boost/asio/detail/task_io_service_operation.hpp (original)
+++ trunk/boost/asio/detail/task_io_service_operation.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -16,6 +16,7 @@
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
 #include <boost/system/error_code.hpp>
+#include <boost/asio/detail/handler_tracking.hpp>
 #include <boost/asio/detail/op_queue.hpp>
 #include <boost/asio/detail/task_io_service_fwd.hpp>
 
@@ -27,7 +28,7 @@
 
 // Base class for all operations. A function pointer is used instead of virtual
 // functions to avoid the associated overhead.
-class task_io_service_operation
+class task_io_service_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER
 {
 public:
   void complete(task_io_service& owner)

Modified: trunk/boost/asio/detail/wait_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/wait_handler.hpp (original)
+++ trunk/boost/asio/detail/wait_handler.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -46,6 +46,8 @@
     wait_handler* h(static_cast<wait_handler*>(base));
     ptr p = { boost::addressof(h->handler_), h, h };
 
+ BOOST_ASIO_HANDLER_COMPLETION((h));
+
     // 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
@@ -61,7 +63,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_handle_read_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_handle_read_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_handle_read_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -56,6 +56,8 @@
     win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     if (owner)
     {
@@ -84,7 +86,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_handle_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_handle_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_handle_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -136,7 +136,19 @@
   void async_write_some(implementation_type& impl,
       const ConstBufferSequence& buffers, Handler& handler)
   {
- async_write_some_at(impl, 0, buffers, handler);
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(buffers, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some"));
+
+ start_write_op(impl, 0,
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::first(buffers), p.p);
+ p.v = p.p = 0;
   }
 
   // Start an asynchronous write at a specified offset. The data being written
@@ -152,6 +164,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some_at"));
+
     start_write_op(impl, offset,
         buffer_sequence_adapter<boost::asio::const_buffer,
           ConstBufferSequence>::first(buffers), p.p);
@@ -184,7 +198,19 @@
   void async_read_some(implementation_type& impl,
       const MutableBufferSequence& buffers, Handler& handler)
   {
- async_read_some_at(impl, 0, buffers, handler);
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(buffers, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some"));
+
+ start_read_op(impl, 0,
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::first(buffers), p.p);
+ p.v = p.p = 0;
   }
 
   // Start an asynchronous read at a specified offset. The buffer for the data
@@ -201,6 +227,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some_at"));
+
     start_read_op(impl, offset,
         buffer_sequence_adapter<boost::asio::mutable_buffer,
           MutableBufferSequence>::first(buffers), p.p);

Modified: trunk/boost/asio/detail/win_iocp_handle_write_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_handle_write_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_handle_write_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -55,6 +55,8 @@
     win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     if (owner)
     {
@@ -79,7 +81,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_null_buffers_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_null_buffers_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_null_buffers_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -62,6 +62,8 @@
     win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // The reactor may have stored a result in the operation object.
     if (o->ec_)
       ec = o->ec_;
@@ -94,7 +96,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_operation.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_operation.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_operation.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -19,6 +19,7 @@
 
 #if defined(BOOST_ASIO_HAS_IOCP)
 
+#include <boost/asio/detail/handler_tracking.hpp>
 #include <boost/asio/detail/op_queue.hpp>
 #include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
 #include <boost/system/error_code.hpp>
@@ -33,6 +34,7 @@
 // functions to avoid the associated overhead.
 class win_iocp_operation
   : public OVERLAPPED
+ BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
 {
 public:
   void complete(win_iocp_io_service& owner,

Modified: trunk/boost/asio/detail/win_iocp_overlapped_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_overlapped_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_overlapped_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -52,6 +52,8 @@
     win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -67,7 +69,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_overlapped_ptr.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_overlapped_ptr.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_overlapped_ptr.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -82,6 +82,10 @@
       boost_asio_handler_alloc_helpers::allocate(
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "io_service",
+ &io_service.impl_, "overlapped"));
+
     io_service.impl_.work_started();
     reset();
     ptr_ = p.p;

Modified: trunk/boost/asio/detail/win_iocp_socket_accept_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_accept_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_accept_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -118,6 +118,8 @@
         *o->peer_endpoint_ = peer_endpoint;
     }
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
     // 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
@@ -133,7 +135,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_socket_recv_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_recv_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_recv_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -59,6 +59,8 @@
     win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     // Check whether buffers are still valid.
     if (owner)
@@ -88,7 +90,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -66,6 +66,8 @@
         static_cast<win_iocp_socket_recvfrom_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     // Check whether buffers are still valid.
     if (owner)
@@ -95,7 +97,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -62,6 +62,8 @@
         static_cast<win_iocp_socket_recvmsg_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     // Check whether buffers are still valid.
     if (owner)
@@ -89,7 +91,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_socket_send_op.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_send_op.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_send_op.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -57,6 +57,8 @@
     win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));
     ptr p = { boost::addressof(o->handler_), o, o };
 
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
     // Check whether buffers are still valid.
     if (owner)
@@ -83,7 +85,9 @@
     if (owner)
     {
       boost::asio::detail::fenced_block b;
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
       boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
     }
   }
 

Modified: trunk/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -267,6 +267,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+
     buffer_sequence_adapter<boost::asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
@@ -288,6 +290,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send_to(null_buffers)"));
+
     start_reactor_op(impl, reactor::write_op, p.p);
     p.v = p.p = 0;
   }
@@ -344,6 +349,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive_from"));
+
     buffer_sequence_adapter<boost::asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
@@ -365,6 +372,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_from(null_buffers)"));
+
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
 
@@ -417,6 +427,8 @@
     p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
         peer_endpoint, enable_connection_aborted, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+
     start_accept_op(impl, peer.is_open(), p.p->new_socket(),
         impl.protocol_.family(), impl.protocol_.type(),
         impl.protocol_.protocol(), p.p->output_buffer(),
@@ -445,6 +457,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.socket_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+
     start_connect_op(impl, p.p, peer_endpoint.data(),
         static_cast<int>(peer_endpoint.size()));
     p.v = p.p = 0;

Modified: trunk/boost/asio/detail/win_iocp_socket_service_base.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_service_base.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_socket_service_base.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -216,6 +216,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+
     buffer_sequence_adapter<boost::asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
@@ -237,6 +239,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send(null_buffers)"));
+
     start_reactor_op(impl, reactor::write_op, p.p);
     p.v = p.p = 0;
   }
@@ -278,6 +283,8 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+
     buffer_sequence_adapter<boost::asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
@@ -299,6 +306,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive(null_buffers)"));
+
     start_null_buffers_receive_op(impl, flags, p.p);
     p.v = p.p = 0;
   }
@@ -347,6 +357,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_with_flags"));
+
     buffer_sequence_adapter<boost::asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
@@ -367,6 +380,9 @@
         sizeof(op), handler), 0 };
     p.p = new (p.v) op(impl.cancel_token_, handler);
 
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_with_flags(null_buffers)"));
+
     // Reset out_flags since it can be given no sensible value at this time.
     out_flags = 0;
 

Added: trunk/boost/asio/detail/win_static_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/win_static_mutex.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,72 @@
+//
+// detail/win_static_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_WIN_STATIC_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_WIN_STATIC_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct win_static_mutex
+{
+ typedef boost::asio::detail::scoped_lock<win_static_mutex> scoped_lock;
+
+ // Initialise the mutex.
+ BOOST_ASIO_DECL void init();
+
+ // Initialisation must be performed in a separate function to the "public"
+ // init() function since the compiler does not support the use of structured
+ // exceptions and C++ exceptions in the same function.
+ BOOST_ASIO_DECL int do_init();
+
+ // Lock the mutex.
+ void lock()
+ {
+ ::EnterCriticalSection(&crit_section_);
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ ::LeaveCriticalSection(&crit_section_);
+ }
+
+ bool initialised_;
+ ::CRITICAL_SECTION crit_section_;
+};
+
+#define BOOST_ASIO_WIN_STATIC_MUTEX_INIT { false, { 0 } }
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/win_static_mutex.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // BOOST_ASIO_DETAIL_WIN_STATIC_MUTEX_HPP

Modified: trunk/boost/asio/impl/src.hpp
==============================================================================
--- trunk/boost/asio/impl/src.hpp (original)
+++ trunk/boost/asio/impl/src.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -26,6 +26,7 @@
 #include <boost/asio/detail/impl/dev_poll_reactor.ipp>
 #include <boost/asio/detail/impl/epoll_reactor.ipp>
 #include <boost/asio/detail/impl/eventfd_select_interrupter.ipp>
+#include <boost/asio/detail/impl/handler_tracking.ipp>
 #include <boost/asio/detail/impl/kqueue_reactor.ipp>
 #include <boost/asio/detail/impl/pipe_select_interrupter.ipp>
 #include <boost/asio/detail/impl/posix_event.ipp>
@@ -38,6 +39,7 @@
 #include <boost/asio/detail/impl/resolver_service_base.ipp>
 #include <boost/asio/detail/impl/select_reactor.ipp>
 #include <boost/asio/detail/impl/service_registry.ipp>
+#include <boost/asio/detail/impl/signal_set_service.ipp>
 #include <boost/asio/detail/impl/socket_ops.ipp>
 #include <boost/asio/detail/impl/socket_select_interrupter.ipp>
 #include <boost/asio/detail/impl/strand_service.ipp>
@@ -51,6 +53,7 @@
 #include <boost/asio/detail/impl/win_iocp_socket_service_base.ipp>
 #include <boost/asio/detail/impl/win_event.ipp>
 #include <boost/asio/detail/impl/win_mutex.ipp>
+#include <boost/asio/detail/impl/win_static_mutex.ipp>
 #include <boost/asio/detail/impl/win_thread.ipp>
 #include <boost/asio/detail/impl/win_tss_ptr.ipp>
 #include <boost/asio/detail/impl/winsock_init.ipp>

Modified: trunk/boost/asio/ip/basic_resolver_iterator.hpp
==============================================================================
--- trunk/boost/asio/ip/basic_resolver_iterator.hpp (original)
+++ trunk/boost/asio/ip/basic_resolver_iterator.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -16,8 +16,9 @@
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
 #include <boost/asio/detail/config.hpp>
-#include <boost/iterator.hpp>
+#include <cstddef>
 #include <cstring>
+#include <iterator>
 #include <string>
 #include <vector>
 #include <boost/asio/detail/shared_ptr.hpp>
@@ -45,15 +46,23 @@
  */
 template <typename InternetProtocol>
 class basic_resolver_iterator
-#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:
+ /// The type used for the distance between two iterators.
+ typedef std::ptrdiff_t difference_type;
+
+ /// The type of the value pointed to by the iterator.
+ typedef basic_resolver_entry<InternetProtocol> value_type;
+
+ /// The type of the result of applying operator->() to the iterator.
+ typedef const basic_resolver_entry<InternetProtocol>* pointer;
+
+ /// The type of the result of applying operator*() to the iterator.
+ typedef const basic_resolver_entry<InternetProtocol>& reference;
+
+ /// The iterator category.
+ typedef std::forward_iterator_tag iterator_category;
+
   /// Default constructor creates an end iterator.
   basic_resolver_iterator()
     : index_(0)

Modified: trunk/boost/asio/placeholders.hpp
==============================================================================
--- trunk/boost/asio/placeholders.hpp (original)
+++ trunk/boost/asio/placeholders.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -39,9 +39,14 @@
 
 /// An argument placeholder, for use with boost::bind(), that corresponds to
 /// the iterator argument of a handler for asynchronous functions such as
-/// boost::asio::basic_resolver::resolve.
+/// boost::asio::basic_resolver::async_resolve.
 unspecified iterator;
 
+/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the signal_number argument of a handler for asynchronous functions such as
+/// boost::asio::signal_set::async_wait.
+unspecified signal_number;
+
 #elif defined(__BORLANDC__) || defined(__GNUC__)
 
 inline boost::arg<1> error()
@@ -59,6 +64,11 @@
   return boost::arg<2>();
 }
 
+inline boost::arg<2> signal_number()
+{
+ return boost::arg<2>();
+}
+
 #else
 
 namespace detail
@@ -82,6 +92,8 @@
   = boost::asio::placeholders::detail::placeholder<2>::get();
 static boost::arg<2>& iterator
   = boost::asio::placeholders::detail::placeholder<2>::get();
+static boost::arg<2>& signal_number
+ = boost::asio::placeholders::detail::placeholder<2>::get();
 
 #else
 
@@ -93,6 +105,8 @@
     = boost::asio::placeholders::detail::placeholder<2>::get();
   boost::arg<2>& iterator
     = boost::asio::placeholders::detail::placeholder<2>::get();
+ boost::arg<2>& signal_number
+ = boost::asio::placeholders::detail::placeholder<2>::get();
 } // namespace
 
 #endif

Added: trunk/boost/asio/signal_set.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/signal_set.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,30 @@
+//
+// signal_set.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_SIGNAL_SET_HPP
+#define BOOST_ASIO_SIGNAL_SET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_signal_set.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Typedef for the typical usage of a signal set.
+typedef basic_signal_set<> signal_set;
+
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_SIGNAL_SET_HPP

Added: trunk/boost/asio/signal_set_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/signal_set_service.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,120 @@
+//
+// signal_set_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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_SIGNAL_SET_SERVICE_HPP
+#define BOOST_ASIO_SIGNAL_SET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/signal_set_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a signal set.
+class signal_set_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<signal_set_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+public:
+ /// The type of a signal set implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef detail::signal_set_service::implementation_type implementation_type;
+#endif
+
+ /// Construct a new signal set service for the specified io_service.
+ explicit signal_set_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<signal_set_service>(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 signal set implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a signal set implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Add a signal to a signal_set.
+ boost::system::error_code add(implementation_type& impl,
+ int signal_number, boost::system::error_code& ec)
+ {
+ return service_impl_.add(impl, signal_number, ec);
+ }
+
+ /// Remove a signal to a signal_set.
+ boost::system::error_code remove(implementation_type& impl,
+ int signal_number, boost::system::error_code& ec)
+ {
+ return service_impl_.remove(impl, signal_number, ec);
+ }
+
+ /// Remove all signals from a signal_set.
+ boost::system::error_code clear(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.clear(impl, ec);
+ }
+
+ /// Cancel all operations associated with the signal set.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ // Start an asynchronous operation to wait for a signal to be delivered.
+ template <typename SignalHandler>
+ void async_wait(implementation_type& impl, SignalHandler handler)
+ {
+ service_impl_.async_wait(impl, handler);
+ }
+
+private:
+ // The platform-specific implementation.
+ detail::signal_set_service service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SIGNAL_SET_SERVICE_HPP

Modified: trunk/boost/asio/version.hpp
==============================================================================
--- trunk/boost/asio/version.hpp (original)
+++ trunk/boost/asio/version.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -18,6 +18,6 @@
 // BOOST_ASIO_VERSION % 100 is the sub-minor version
 // BOOST_ASIO_VERSION / 100 % 1000 is the minor version
 // BOOST_ASIO_VERSION / 100000 is the major version
-#define BOOST_ASIO_VERSION 100500 // 1.5.0
+#define BOOST_ASIO_VERSION 100501 // 1.5.1
 
 #endif // BOOST_ASIO_VERSION_HPP

Modified: trunk/libs/asio/doc/examples.qbk
==============================================================================
--- trunk/libs/asio/doc/examples.qbk (original)
+++ trunk/libs/asio/doc/examples.qbk 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -74,9 +74,9 @@
 * [@boost_asio/example/http/server/connection_manager.cpp]
 * [@boost_asio/example/http/server/connection_manager.hpp]
 * [@boost_asio/example/http/server/header.hpp]
+* [@boost_asio/example/http/server/main.cpp]
 * [@boost_asio/example/http/server/mime_types.cpp]
 * [@boost_asio/example/http/server/mime_types.hpp]
-* [@boost_asio/example/http/server/posix_main.cpp]
 * [@boost_asio/example/http/server/reply.cpp]
 * [@boost_asio/example/http/server/reply.hpp]
 * [@boost_asio/example/http/server/request.hpp]
@@ -86,7 +86,6 @@
 * [@boost_asio/example/http/server/request_parser.hpp]
 * [@boost_asio/example/http/server/server.cpp]
 * [@boost_asio/example/http/server/server.hpp]
-* [@boost_asio/example/http/server/win_main.cpp]
 
 
 [heading HTTP Server 2]
@@ -98,9 +97,9 @@
 * [@boost_asio/example/http/server2/header.hpp]
 * [@boost_asio/example/http/server2/io_service_pool.cpp]
 * [@boost_asio/example/http/server2/io_service_pool.hpp]
+* [@boost_asio/example/http/server2/main.cpp]
 * [@boost_asio/example/http/server2/mime_types.cpp]
 * [@boost_asio/example/http/server2/mime_types.hpp]
-* [@boost_asio/example/http/server2/posix_main.cpp]
 * [@boost_asio/example/http/server2/reply.cpp]
 * [@boost_asio/example/http/server2/reply.hpp]
 * [@boost_asio/example/http/server2/request.hpp]
@@ -110,7 +109,6 @@
 * [@boost_asio/example/http/server2/request_parser.hpp]
 * [@boost_asio/example/http/server2/server.cpp]
 * [@boost_asio/example/http/server2/server.hpp]
-* [@boost_asio/example/http/server2/win_main.cpp]
 
 
 [heading HTTP Server 3]
@@ -120,9 +118,9 @@
 * [@boost_asio/example/http/server3/connection.cpp]
 * [@boost_asio/example/http/server3/connection.hpp]
 * [@boost_asio/example/http/server3/header.hpp]
+* [@boost_asio/example/http/server3/main.cpp]
 * [@boost_asio/example/http/server3/mime_types.cpp]
 * [@boost_asio/example/http/server3/mime_types.hpp]
-* [@boost_asio/example/http/server3/posix_main.cpp]
 * [@boost_asio/example/http/server3/reply.cpp]
 * [@boost_asio/example/http/server3/reply.hpp]
 * [@boost_asio/example/http/server3/request.hpp]
@@ -132,7 +130,6 @@
 * [@boost_asio/example/http/server3/request_parser.hpp]
 * [@boost_asio/example/http/server3/server.cpp]
 * [@boost_asio/example/http/server3/server.hpp]
-* [@boost_asio/example/http/server3/win_main.cpp]
 
 
 [heading HTTP Server 4]
@@ -143,9 +140,9 @@
 * [@boost_asio/example/http/server4/file_handler.cpp]
 * [@boost_asio/example/http/server4/file_handler.hpp]
 * [@boost_asio/example/http/server4/header.hpp]
+* [@boost_asio/example/http/server4/main.cpp]
 * [@boost_asio/example/http/server4/mime_types.cpp]
 * [@boost_asio/example/http/server4/mime_types.hpp]
-* [@boost_asio/example/http/server4/posix_main.cpp]
 * [@boost_asio/example/http/server4/reply.cpp]
 * [@boost_asio/example/http/server4/reply.hpp]
 * [@boost_asio/example/http/server4/request.hpp]
@@ -154,7 +151,6 @@
 * [@boost_asio/example/http/server4/server.cpp]
 * [@boost_asio/example/http/server4/server.hpp]
 * [@boost_asio/example/http/server4/unyield.hpp]
-* [@boost_asio/example/http/server4/win_main.cpp]
 * [@boost_asio/example/http/server4/yield.hpp]
 
 

Modified: trunk/libs/asio/doc/quickref.xml
==============================================================================
--- trunk/libs/asio/doc/quickref.xml (original)
+++ trunk/libs/asio/doc/quickref.xml 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -86,6 +86,7 @@
             <member><link linkend="boost_asio.reference.placeholders__bytes_transferred">placeholders::bytes_transferred</link></member>
             <member><link linkend="boost_asio.reference.placeholders__error">placeholders::error</link></member>
             <member><link linkend="boost_asio.reference.placeholders__iterator">placeholders::iterator</link></member>
+ <member><link linkend="boost_asio.reference.placeholders__signal_number">placeholders::signal_number</link></member>
           </simplelist>
           <bridgehead renderas="sect3">Error Codes</bridgehead>
           <simplelist type="vert" columns="1">
@@ -267,9 +268,12 @@
         <entry valign="center" namest="b" nameend="b">
           <bridgehead renderas="sect2">SSL</bridgehead>
         </entry>
- <entry valign="center" namest="c" nameend="d">
+ <entry valign="center" namest="c" nameend="c">
           <bridgehead renderas="sect2">Serial Ports</bridgehead>
         </entry>
+ <entry valign="center" namest="d" nameend="d">
+ <bridgehead renderas="sect2">Signal Handling</bridgehead>
+ </entry>
       </row>
     </thead>
     <tbody>
@@ -327,8 +331,6 @@
           <simplelist type="vert" columns="1">
             <member><link linkend="boost_asio.reference.serial_port_service">serial_port_service</link></member>
           </simplelist>
- </entry>
- <entry valign="top">
           <bridgehead renderas="sect3">Serial Port Options</bridgehead>
           <simplelist type="vert" columns="1">
             <member><link linkend="boost_asio.reference.serial_port_base__baud_rate">serial_port_base::baud_rate</link></member>
@@ -344,6 +346,25 @@
             <member><link linkend="boost_asio.reference.SettableSerialPortOption">SettableSerialPortOption</link></member>
           </simplelist>
         </entry>
+ <entry valign="top">
+ <bridgehead renderas="sect3">Classes</bridgehead>
+ <simplelist type="vert" columns="1">
+ <member><link linkend="boost_asio.reference.signal_set">signal_set</link></member>
+ </simplelist>
+ <bridgehead renderas="sect3">Class Templates</bridgehead>
+ <simplelist type="vert" columns="1">
+ <member><link linkend="boost_asio.reference.basic_signal_set">basic_signal_set</link></member>
+ </simplelist>
+ <bridgehead renderas="sect3">Services</bridgehead>
+ <simplelist type="vert" columns="1">
+ <member><link linkend="boost_asio.reference.signal_set_service">signal_set_service</link></member>
+ </simplelist>
+ <bridgehead renderas="sect3">Type Requirements</bridgehead>
+ <simplelist type="vert" columns="1">
+ <member><link linkend="boost_asio.reference.SignalSetService">SignalSetService</link></member>
+ <member><link linkend="boost_asio.reference.SignalHandler">SignalHandler</link></member>
+ </simplelist>
+ </entry>
       </row>
     </tbody>
   </tgroup>

Modified: trunk/libs/asio/doc/reference.qbk
==============================================================================
--- trunk/libs/asio/doc/reference.qbk (original)
+++ trunk/libs/asio/doc/reference.qbk 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -43,6 +43,8 @@
 [include requirements/Service.qbk]
 [include requirements/SettableSerialPortOption.qbk]
 [include requirements/SettableSocketOption.qbk]
+[include requirements/SignalHandler.qbk]
+[include requirements/SignalSetService.qbk]
 [include requirements/SocketAcceptorService.qbk]
 [include requirements/SocketService.qbk]
 [include requirements/StreamDescriptorService.qbk]
@@ -21756,6 +21758,904 @@
 
 [endsect]
 
+[section:basic_signal_set basic_signal_set]
+
+
+Provides signal functionality.
+
+
+ template<
+ typename ``[link boost_asio.reference.SignalSetService SignalSetService]`` = signal_set_service>
+ class basic_signal_set :
+ public basic_io_object< SignalSetService >
+
+
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.basic_signal_set.implementation_type [*implementation_type]]]
+ [The underlying implementation type of I/O object. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.basic_signal_set.service_type [*service_type]]]
+ [The type of the service that will be used to provide I/O operations. ]
+
+ ]
+
+]
+
+[heading Member Functions]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.add [*add]]]
+ [Add a signal to a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.async_wait [*async_wait]]]
+ [Start an asynchronous operation to wait for a signal to be delivered. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.basic_signal_set [*basic_signal_set]]]
+ [Construct a signal set without adding any signals.
+
+ Construct a signal set and add one signal.
+
+ Construct a signal set and add two signals.
+
+ Construct a signal set and add three signals. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.cancel [*cancel]]]
+ [Cancel all operations associated with the signal set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.clear [*clear]]]
+ [Remove all signals from a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.get_io_service [*get_io_service]]]
+ [Get the io_service associated with the object. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.remove [*remove]]]
+ [Remove a signal from a signal_set. ]
+ ]
+
+]
+
+[heading Protected Data Members]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.implementation [*implementation]]]
+ [The underlying implementation of the I/O object. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.service [*service]]]
+ [The service associated with the I/O object. ]
+ ]
+
+]
+
+The [link boost_asio.reference.basic_signal_set `basic_signal_set`] class template provides the ability to perform an asynchronous wait for one or more signals to occur.
+
+Most applications will use the `boost::asio::signal_set` typedef.
+
+
+[heading Thread Safety]
+
+[*Distinct] [*objects:] Safe.
+
+[*Shared] [*objects:] Unsafe.
+
+
+[heading Example]
+
+Performing an asynchronous wait:
+
+ void handler(
+ const boost::system::error_code& error,
+ int signal_number)
+ {
+ if (!error)
+ {
+ // A signal occurred.
+ }
+ }
+
+ ...
+
+ // Construct a signal set registered for process termination.
+ boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
+
+ // Start an asynchronous wait for one of the signals to occur.
+ signals.async_wait(handler);
+
+
+
+
+
+[heading Queueing of signal notifications]
+
+
+
+If a signal is registered with a signal\_set, and the signal occurs when there are no waiting handlers, then the signal notification is queued. The next async\_wait operation on that signal\_set will dequeue the notification. If multiple notifications are queued, subsequent async\_wait operations dequeue them one at a time. Signal notifications are dequeued in order of ascending signal number.
+
+If a signal number is removed from a signal\_set (using the `remove` or `erase` member functions) then any queued notifications for that signal are discarded.
+
+
+[heading Multiple registration of signals]
+
+
+
+The same signal number may be registered with different signal\_set objects. When the signal occurs, one handler is called for each signal\_set object.
+
+Note that multiple registration only works for signals that are registered using Asio. The application must not also register a signal handler using functions such as `signal()` or `sigaction()`.
+
+
+[heading Signal masking on POSIX platforms]
+
+
+
+POSIX allows signals to be blocked using functions such as `sigprocmask()` and `pthread_sigmask()`. For signals to be delivered, programs must ensure that any signals registered using signal\_set objects are unblocked in at least one thread.
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/basic_signal_set.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+[section:add basic_signal_set::add]
+
+[indexterm2 add..basic_signal_set]
+Add a signal to a signal\_set.
+
+
+ void ``[link boost_asio.reference.basic_signal_set.add.overload1 add]``(
+ int signal_number);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.add.overload1 more...]]``
+
+ boost::system::error_code ``[link boost_asio.reference.basic_signal_set.add.overload2 add]``(
+ int signal_number,
+ boost::system::error_code & ec);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.add.overload2 more...]]``
+
+
+[section:overload1 basic_signal_set::add (1 of 2 overloads)]
+
+
+Add a signal to a signal\_set.
+
+
+ void add(
+ int signal_number);
+
+
+This function adds the specified signal to the set. It has no effect if the signal is already in the set.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[signal_number][The signal to be added to the set.]]
+
+]
+
+
+[heading Exceptions]
+
+
+[variablelist
+
+[[boost::system::system_error][Thrown on failure. ]]
+
+]
+
+
+
+
+[endsect]
+
+
+
+[section:overload2 basic_signal_set::add (2 of 2 overloads)]
+
+
+Add a signal to a signal\_set.
+
+
+ boost::system::error_code add(
+ int signal_number,
+ boost::system::error_code & ec);
+
+
+This function adds the specified signal to the set. It has no effect if the signal is already in the set.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[signal_number][The signal to be added to the set.]]
+
+[[ec][Set to indicate what error occurred, if any. ]]
+
+]
+
+
+
+
+[endsect]
+
+
+[endsect]
+
+
+[section:async_wait basic_signal_set::async_wait]
+
+[indexterm2 async_wait..basic_signal_set]
+Start an asynchronous operation to wait for a signal to be delivered.
+
+
+ template<
+ typename ``[link boost_asio.reference.SignalHandler SignalHandler]``>
+ void async_wait(
+ SignalHandler handler);
+
+
+This function may be used to initiate an asynchronous wait against the signal set. It always returns immediately.
+
+For each call to `async_wait()`, the supplied handler will be called exactly once. The handler will be called when:
+
+
+* One of the registered signals in the signal set occurs; or
+
+
+* The signal set was cancelled, in which case the handler is passed the error code `boost::asio::error::operation_aborted`.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[handler][The handler to be called when the signal occurs. Copies will be made of the handler as required. The function signature of the handler must be:
+``
+ void handler(
+ const boost::system::error_code& error, // Result of operation.
+ int signal_number // Indicates which signal occurred.
+ );
+``
+Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using `boost::asio::io_service::post()`. ]]
+
+]
+
+
+
+
+[endsect]
+
+
+[section:basic_signal_set basic_signal_set::basic_signal_set]
+
+[indexterm2 basic_signal_set..basic_signal_set]
+Construct a signal set without adding any signals.
+
+
+ explicit ``[link boost_asio.reference.basic_signal_set.basic_signal_set.overload1 basic_signal_set]``(
+ boost::asio::io_service & io_service);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.basic_signal_set.overload1 more...]]``
+
+
+Construct a signal set and add one signal.
+
+
+ ``[link boost_asio.reference.basic_signal_set.basic_signal_set.overload2 basic_signal_set]``(
+ boost::asio::io_service & io_service,
+ int signal_number_1);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.basic_signal_set.overload2 more...]]``
+
+
+Construct a signal set and add two signals.
+
+
+ ``[link boost_asio.reference.basic_signal_set.basic_signal_set.overload3 basic_signal_set]``(
+ boost::asio::io_service & io_service,
+ int signal_number_1,
+ int signal_number_2);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.basic_signal_set.overload3 more...]]``
+
+
+Construct a signal set and add three signals.
+
+
+ ``[link boost_asio.reference.basic_signal_set.basic_signal_set.overload4 basic_signal_set]``(
+ boost::asio::io_service & io_service,
+ int signal_number_1,
+ int signal_number_2,
+ int signal_number_3);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.basic_signal_set.overload4 more...]]``
+
+
+[section:overload1 basic_signal_set::basic_signal_set (1 of 4 overloads)]
+
+
+Construct a signal set without adding any signals.
+
+
+ basic_signal_set(
+ boost::asio::io_service & io_service);
+
+
+This constructor creates a signal set without registering for any signals.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[io_service][The [link boost_asio.reference.io_service `io_service`] object that the signal set will use to dispatch handlers for any asynchronous operations performed on the set. ]]
+
+]
+
+
+
+
+[endsect]
+
+
+
+[section:overload2 basic_signal_set::basic_signal_set (2 of 4 overloads)]
+
+
+Construct a signal set and add one signal.
+
+
+ basic_signal_set(
+ boost::asio::io_service & io_service,
+ int signal_number_1);
+
+
+This constructor creates a signal set and registers for one signal.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[io_service][The [link boost_asio.reference.io_service `io_service`] object that the signal set will use to dispatch handlers for any asynchronous operations performed on the set.]]
+
+[[signal_number_1][The signal number to be added.]]
+
+]
+
+
+[heading Remarks]
+
+This constructor is equivalent to performing:
+
+ boost::asio::signal_set signals(io_service);
+ signals.add(signal_number_1);
+
+
+
+
+
+
+
+[endsect]
+
+
+
+[section:overload3 basic_signal_set::basic_signal_set (3 of 4 overloads)]
+
+
+Construct a signal set and add two signals.
+
+
+ basic_signal_set(
+ boost::asio::io_service & io_service,
+ int signal_number_1,
+ int signal_number_2);
+
+
+This constructor creates a signal set and registers for two signals.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[io_service][The [link boost_asio.reference.io_service `io_service`] object that the signal set will use to dispatch handlers for any asynchronous operations performed on the set.]]
+
+[[signal_number_1][The first signal number to be added.]]
+
+[[signal_number_2][The second signal number to be added.]]
+
+]
+
+
+[heading Remarks]
+
+This constructor is equivalent to performing:
+
+ boost::asio::signal_set signals(io_service);
+ signals.add(signal_number_1);
+ signals.add(signal_number_2);
+
+
+
+
+
+
+
+[endsect]
+
+
+
+[section:overload4 basic_signal_set::basic_signal_set (4 of 4 overloads)]
+
+
+Construct a signal set and add three signals.
+
+
+ basic_signal_set(
+ boost::asio::io_service & io_service,
+ int signal_number_1,
+ int signal_number_2,
+ int signal_number_3);
+
+
+This constructor creates a signal set and registers for three signals.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[io_service][The [link boost_asio.reference.io_service `io_service`] object that the signal set will use to dispatch handlers for any asynchronous operations performed on the set.]]
+
+[[signal_number_1][The first signal number to be added.]]
+
+[[signal_number_2][The second signal number to be added.]]
+
+[[signal_number_3][The third signal number to be added.]]
+
+]
+
+
+[heading Remarks]
+
+This constructor is equivalent to performing:
+
+ boost::asio::signal_set signals(io_service);
+ signals.add(signal_number_1);
+ signals.add(signal_number_2);
+ signals.add(signal_number_3);
+
+
+
+
+
+
+
+[endsect]
+
+
+[endsect]
+
+[section:cancel basic_signal_set::cancel]
+
+[indexterm2 cancel..basic_signal_set]
+Cancel all operations associated with the signal set.
+
+
+ void ``[link boost_asio.reference.basic_signal_set.cancel.overload1 cancel]``();
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.cancel.overload1 more...]]``
+
+ boost::system::error_code ``[link boost_asio.reference.basic_signal_set.cancel.overload2 cancel]``(
+ boost::system::error_code & ec);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.cancel.overload2 more...]]``
+
+
+[section:overload1 basic_signal_set::cancel (1 of 2 overloads)]
+
+
+Cancel all operations associated with the signal set.
+
+
+ void cancel();
+
+
+This function forces the completion of any pending asynchronous wait operations against the signal set. The handler for each cancelled operation will be invoked with the `boost::asio::error::operation_aborted` error code.
+
+Cancellation does not alter the set of registered signals.
+
+
+[heading Exceptions]
+
+
+[variablelist
+
+[[boost::system::system_error][Thrown on failure.]]
+
+]
+
+
+[heading Remarks]
+
+If a registered signal occurred before `cancel()` is called, then the handlers for asynchronous wait operations will:
+
+
+* have already been invoked; or
+
+
+* have been queued for invocation in the near future.
+
+These handlers can no longer be cancelled, and therefore are passed an error code that indicates the successful completion of the wait operation.
+
+
+[endsect]
+
+
+
+[section:overload2 basic_signal_set::cancel (2 of 2 overloads)]
+
+
+Cancel all operations associated with the signal set.
+
+
+ boost::system::error_code cancel(
+ boost::system::error_code & ec);
+
+
+This function forces the completion of any pending asynchronous wait operations against the signal set. The handler for each cancelled operation will be invoked with the `boost::asio::error::operation_aborted` error code.
+
+Cancellation does not alter the set of registered signals.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[ec][Set to indicate what error occurred, if any.]]
+
+]
+
+
+[heading Remarks]
+
+If a registered signal occurred before `cancel()` is called, then the handlers for asynchronous wait operations will:
+
+
+* have already been invoked; or
+
+
+* have been queued for invocation in the near future.
+
+These handlers can no longer be cancelled, and therefore are passed an error code that indicates the successful completion of the wait operation.
+
+
+[endsect]
+
+
+[endsect]
+
+[section:clear basic_signal_set::clear]
+
+[indexterm2 clear..basic_signal_set]
+Remove all signals from a signal\_set.
+
+
+ void ``[link boost_asio.reference.basic_signal_set.clear.overload1 clear]``();
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.clear.overload1 more...]]``
+
+ boost::system::error_code ``[link boost_asio.reference.basic_signal_set.clear.overload2 clear]``(
+ boost::system::error_code & ec);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.clear.overload2 more...]]``
+
+
+[section:overload1 basic_signal_set::clear (1 of 2 overloads)]
+
+
+Remove all signals from a signal\_set.
+
+
+ void clear();
+
+
+This function removes all signals from the set. It has no effect if the set is already empty.
+
+
+[heading Exceptions]
+
+
+[variablelist
+
+[[boost::system::system_error][Thrown on failure.]]
+
+]
+
+
+[heading Remarks]
+
+Removes all queued notifications.
+
+
+
+
+[endsect]
+
+
+
+[section:overload2 basic_signal_set::clear (2 of 2 overloads)]
+
+
+Remove all signals from a signal\_set.
+
+
+ boost::system::error_code clear(
+ boost::system::error_code & ec);
+
+
+This function removes all signals from the set. It has no effect if the set is already empty.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[ec][Set to indicate what error occurred, if any.]]
+
+]
+
+
+[heading Remarks]
+
+Removes all queued notifications.
+
+
+
+
+[endsect]
+
+
+[endsect]
+
+
+[section:get_io_service basic_signal_set::get_io_service]
+
+
+['Inherited from basic_io_object.]
+
+[indexterm2 get_io_service..basic_signal_set]
+Get the [link boost_asio.reference.io_service `io_service`] associated with the object.
+
+
+ boost::asio::io_service & get_io_service();
+
+
+This function may be used to obtain the [link boost_asio.reference.io_service `io_service`] object that the I/O object uses to dispatch handlers for asynchronous operations.
+
+
+[heading Return Value]
+
+A reference to the [link boost_asio.reference.io_service `io_service`] object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller.
+
+
+
+
+[endsect]
+
+
+
+[section:implementation basic_signal_set::implementation]
+
+
+['Inherited from basic_io_object.]
+
+[indexterm2 implementation..basic_signal_set]
+The underlying implementation of the I/O object.
+
+
+ implementation_type implementation;
+
+
+
+[endsect]
+
+
+
+[section:implementation_type basic_signal_set::implementation_type]
+
+
+['Inherited from basic_io_object.]
+
+[indexterm2 implementation_type..basic_signal_set]
+The underlying implementation type of I/O object.
+
+
+ typedef service_type::implementation_type implementation_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/basic_signal_set.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+[section:remove basic_signal_set::remove]
+
+[indexterm2 remove..basic_signal_set]
+Remove a signal from a signal\_set.
+
+
+ void ``[link boost_asio.reference.basic_signal_set.remove.overload1 remove]``(
+ int signal_number);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.remove.overload1 more...]]``
+
+ boost::system::error_code ``[link boost_asio.reference.basic_signal_set.remove.overload2 remove]``(
+ int signal_number,
+ boost::system::error_code & ec);
+ `` [''''&raquo;''' [link boost_asio.reference.basic_signal_set.remove.overload2 more...]]``
+
+
+[section:overload1 basic_signal_set::remove (1 of 2 overloads)]
+
+
+Remove a signal from a signal\_set.
+
+
+ void remove(
+ int signal_number);
+
+
+This function removes the specified signal from the set. It has no effect if the signal is not in the set.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[signal_number][The signal to be removed from the set.]]
+
+]
+
+
+[heading Exceptions]
+
+
+[variablelist
+
+[[boost::system::system_error][Thrown on failure.]]
+
+]
+
+
+[heading Remarks]
+
+Removes any notifications that have been queued for the specified signal number.
+
+
+
+
+[endsect]
+
+
+
+[section:overload2 basic_signal_set::remove (2 of 2 overloads)]
+
+
+Remove a signal from a signal\_set.
+
+
+ boost::system::error_code remove(
+ int signal_number,
+ boost::system::error_code & ec);
+
+
+This function removes the specified signal from the set. It has no effect if the signal is not in the set.
+
+
+[heading Parameters]
+
+
+[variablelist
+
+[[signal_number][The signal to be removed from the set.]]
+
+[[ec][Set to indicate what error occurred, if any.]]
+
+]
+
+
+[heading Remarks]
+
+Removes any notifications that have been queued for the specified signal number.
+
+
+
+
+[endsect]
+
+
+[endsect]
+
+
+[section:service basic_signal_set::service]
+
+
+['Inherited from basic_io_object.]
+
+[indexterm2 service..basic_signal_set]
+The service associated with the I/O object.
+
+
+ service_type & service;
+
+
+
+[endsect]
+
+
+
+[section:service_type basic_signal_set::service_type]
+
+
+['Inherited from basic_io_object.]
+
+[indexterm2 service_type..basic_signal_set]
+The type of the service that will be used to provide I/O operations.
+
+
+ typedef SignalSetService service_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/basic_signal_set.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[endsect]
+
 [section:basic_socket basic_socket]
 
 
@@ -45112,6 +46012,47 @@
   class buffers_iterator
 
 
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.buffers_iterator.difference_type [*difference_type]]]
+ [The type used for the distance between two iterators. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.buffers_iterator.iterator_category [*iterator_category]]]
+ [The iterator category. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.buffers_iterator.pointer [*pointer]]]
+ [The type of the result of applying operator->() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.buffers_iterator.reference [*reference]]]
+ [The type of the result of applying operator*() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.buffers_iterator.value_type [*value_type]]]
+ [The type of the value pointed to by the iterator. ]
+
+ ]
+
+]
+
 [heading Member Functions]
 [table
   [[Name][Description]]
@@ -45254,6 +46195,27 @@
 
 
 
+[section:difference_type buffers_iterator::difference_type]
+
+[indexterm2 difference_type..buffers_iterator]
+The type used for the distance between two iterators.
+
+
+ typedef std::ptrdiff_t difference_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/buffers_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
 [section:end buffers_iterator::end]
 
 [indexterm2 end..buffers_iterator]
@@ -45269,13 +46231,34 @@
 
 
 
+[section:iterator_category buffers_iterator::iterator_category]
+
+[indexterm2 iterator_category..buffers_iterator]
+The iterator category.
+
+
+ typedef std::random_access_iterator_tag iterator_category;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/buffers_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
 [section:operator__star_ buffers_iterator::operator *]
 
 [indexterm2 operator *..buffers_iterator]
 Dereference an iterator.
 
 
- byte_type & operator *() const;
+ reference operator *() const;
 
 
 
@@ -45561,7 +46544,7 @@
 Dereference an iterator.
 
 
- byte_type * operator->() const;
+ pointer operator->() const;
 
 
 
@@ -45685,7 +46668,7 @@
 Access an individual element.
 
 
- byte_type & operator[](
+ reference operator[](
       std::ptrdiff_t difference) const;
 
 
@@ -45694,6 +46677,73 @@
 
 
 
+[section:pointer buffers_iterator::pointer]
+
+[indexterm2 pointer..buffers_iterator]
+The type of the result of applying `operator->()` to the iterator.
+
+
+ typedef const_or_non_const_ByteType * pointer;
+
+
+
+If the buffer sequence stores buffer objects that are convertible to [link boost_asio.reference.mutable_buffer `mutable_buffer`], this is a pointer to a non-const ByteType. Otherwise, a pointer to a const ByteType.
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/buffers_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:reference buffers_iterator::reference]
+
+[indexterm2 reference..buffers_iterator]
+The type of the result of applying `operator*()` to the iterator.
+
+
+ typedef const_or_non_const_ByteType & reference;
+
+
+
+If the buffer sequence stores buffer objects that are convertible to [link boost_asio.reference.mutable_buffer `mutable_buffer`], this is a reference to a non-const ByteType. Otherwise, a reference to a const ByteType.
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/buffers_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:value_type buffers_iterator::value_type]
+
+[indexterm2 value_type..buffers_iterator]
+The type of the value pointed to by the iterator.
+
+
+ typedef ByteType value_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/buffers_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
 [endsect]
 
 [section:connect connect]
@@ -54571,6 +55621,47 @@
   typedef basic_resolver_iterator< InternetProtocol > iterator;
 
 
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.difference_type [*difference_type]]]
+ [The type used for the distance between two iterators. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.iterator_category [*iterator_category]]]
+ [The iterator category. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.pointer [*pointer]]]
+ [The type of the result of applying operator->() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.reference [*reference]]]
+ [The type of the result of applying operator*() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.value_type [*value_type]]]
+ [The type of the value pointed to by the iterator. ]
+
+ ]
+
+]
+
 [heading Member Functions]
 [table
   [[Name][Description]]
@@ -55298,6 +56389,47 @@
   class basic_resolver_iterator
 
 
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.difference_type [*difference_type]]]
+ [The type used for the distance between two iterators. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.iterator_category [*iterator_category]]]
+ [The iterator category. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.pointer [*pointer]]]
+ [The type of the result of applying operator->() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.reference [*reference]]]
+ [The type of the result of applying operator*() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.value_type [*value_type]]]
+ [The type of the value pointed to by the iterator. ]
+
+ ]
+
+]
+
 [heading Member Functions]
 [table
   [[Name][Description]]
@@ -55446,6 +56578,48 @@
 [endsect]
 
 
+[section:difference_type ip::basic_resolver_iterator::difference_type]
+
+[indexterm2 difference_type..ip::basic_resolver_iterator]
+The type used for the distance between two iterators.
+
+
+ typedef std::ptrdiff_t difference_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/ip/basic_resolver_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:iterator_category ip::basic_resolver_iterator::iterator_category]
+
+[indexterm2 iterator_category..ip::basic_resolver_iterator]
+The iterator category.
+
+
+ typedef std::forward_iterator_tag iterator_category;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/ip/basic_resolver_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
 [section:operator__star_ ip::basic_resolver_iterator::operator *]
 
 [indexterm2 operator *..ip::basic_resolver_iterator]
@@ -55491,68 +56665,259 @@
   `` [''''&raquo;''' [link boost_asio.reference.ip__basic_resolver_iterator.operator_plus__plus_.overload1 more...]]``
 
 
-Increment operator (postfix).
+Increment operator (postfix).
+
+
+ basic_resolver_iterator ``[link boost_asio.reference.ip__basic_resolver_iterator.operator_plus__plus_.overload2 operator++]``(
+ int );
+ `` [''''&raquo;''' [link boost_asio.reference.ip__basic_resolver_iterator.operator_plus__plus_.overload2 more...]]``
+
+
+[section:overload1 ip::basic_resolver_iterator::operator++ (1 of 2 overloads)]
+
+
+Increment operator (prefix).
+
+
+ basic_resolver_iterator & operator++();
+
+
+
+[endsect]
+
+
+
+[section:overload2 ip::basic_resolver_iterator::operator++ (2 of 2 overloads)]
+
+
+Increment operator (postfix).
+
+
+ basic_resolver_iterator operator++(
+ int );
+
+
+
+[endsect]
+
+
+[endsect]
+
+
+[section:operator_arrow_ ip::basic_resolver_iterator::operator->]
+
+[indexterm2 operator->..ip::basic_resolver_iterator]
+Dereference an iterator.
+
+
+ const basic_resolver_entry< InternetProtocol > * operator->() const;
+
+
+
+[endsect]
+
+
+
+[section:operator_eq__eq_ ip::basic_resolver_iterator::operator==]
+
+[indexterm2 operator==..ip::basic_resolver_iterator]
+Test two iterators for equality.
+
+
+ friend bool operator==(
+ const basic_resolver_iterator & a,
+ const basic_resolver_iterator & b);
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/ip/basic_resolver_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:pointer ip::basic_resolver_iterator::pointer]
+
+[indexterm2 pointer..ip::basic_resolver_iterator]
+The type of the result of applying `operator->()` to the iterator.
+
+
+ typedef const basic_resolver_entry< InternetProtocol > * pointer;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/ip/basic_resolver_iterator.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:reference ip::basic_resolver_iterator::reference]
+
+[indexterm2 reference..ip::basic_resolver_iterator]
+The type of the result of applying `operator*()` to the iterator.
+
+
+ typedef const basic_resolver_entry< InternetProtocol > & reference;
+
+
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_entry.endpoint_type [*endpoint_type]]]
+ [The endpoint type associated with the endpoint entry. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_entry.protocol_type [*protocol_type]]]
+ [The protocol type associated with the endpoint entry. ]
+
+ ]
+
+]
 
+[heading Member Functions]
+[table
+ [[Name][Description]]
 
- basic_resolver_iterator ``[link boost_asio.reference.ip__basic_resolver_iterator.operator_plus__plus_.overload2 operator++]``(
- int );
- `` [''''&raquo;''' [link boost_asio.reference.ip__basic_resolver_iterator.operator_plus__plus_.overload2 more...]]``
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.basic_resolver_entry [*basic_resolver_entry]]]
+ [Default constructor.
 
+ Construct with specified endpoint, host name and service name. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.endpoint [*endpoint]]]
+ [Get the endpoint associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.host_name [*host_name]]]
+ [Get the host name associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.operator_endpoint_type [*operator endpoint_type]]]
+ [Convert to the endpoint associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.service_name [*service_name]]]
+ [Get the service name associated with the entry. ]
+ ]
+
+]
 
-[section:overload1 ip::basic_resolver_iterator::operator++ (1 of 2 overloads)]
+The [link boost_asio.reference.ip__basic_resolver_entry `ip::basic_resolver_entry`] class template describes an entry as returned by a resolver.
 
 
-Increment operator (prefix).
+[heading Thread Safety]
+
+[*Distinct] [*objects:] Safe.
 
+[*Shared] [*objects:] Unsafe.
 
- basic_resolver_iterator & operator++();
 
 
 
-[endsect]
+[heading Requirements]
 
+[*Header: ][^boost/asio/ip/basic_resolver_iterator.hpp]
 
+[*Convenience header: ][^boost/asio.hpp]
 
-[section:overload2 ip::basic_resolver_iterator::operator++ (2 of 2 overloads)]
 
+[endsect]
 
-Increment operator (postfix).
 
 
- basic_resolver_iterator operator++(
- int );
+[section:value_type ip::basic_resolver_iterator::value_type]
 
+[indexterm2 value_type..ip::basic_resolver_iterator]
+The type of the value pointed to by the iterator.
 
 
-[endsect]
+ typedef basic_resolver_entry< InternetProtocol > value_type;
 
 
-[endsect]
+[heading Types]
+[table
+ [[Name][Description]]
 
+ [
 
-[section:operator_arrow_ ip::basic_resolver_iterator::operator->]
+ [[link boost_asio.reference.ip__basic_resolver_entry.endpoint_type [*endpoint_type]]]
+ [The endpoint type associated with the endpoint entry. ]
+
+ ]
 
-[indexterm2 operator->..ip::basic_resolver_iterator]
-Dereference an iterator.
+ [
 
+ [[link boost_asio.reference.ip__basic_resolver_entry.protocol_type [*protocol_type]]]
+ [The protocol type associated with the endpoint entry. ]
+
+ ]
 
- const basic_resolver_entry< InternetProtocol > * operator->() const;
+]
 
+[heading Member Functions]
+[table
+ [[Name][Description]]
 
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.basic_resolver_entry [*basic_resolver_entry]]]
+ [Default constructor.
 
-[endsect]
+ Construct with specified endpoint, host name and service name. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.endpoint [*endpoint]]]
+ [Get the endpoint associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.host_name [*host_name]]]
+ [Get the host name associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.operator_endpoint_type [*operator endpoint_type]]]
+ [Convert to the endpoint associated with the entry. ]
+ ]
+
+ [
+ [[link boost_asio.reference.ip__basic_resolver_entry.service_name [*service_name]]]
+ [Get the service name associated with the entry. ]
+ ]
+
+]
 
+The [link boost_asio.reference.ip__basic_resolver_entry `ip::basic_resolver_entry`] class template describes an entry as returned by a resolver.
 
 
-[section:operator_eq__eq_ ip::basic_resolver_iterator::operator==]
+[heading Thread Safety]
+
+[*Distinct] [*objects:] Safe.
 
-[indexterm2 operator==..ip::basic_resolver_iterator]
-Test two iterators for equality.
+[*Shared] [*objects:] Unsafe.
 
 
- friend bool operator==(
- const basic_resolver_iterator & a,
- const basic_resolver_iterator & b);
 
 
 [heading Requirements]
@@ -57830,6 +59195,47 @@
   typedef basic_resolver_iterator< InternetProtocol > iterator_type;
 
 
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.difference_type [*difference_type]]]
+ [The type used for the distance between two iterators. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.iterator_category [*iterator_category]]]
+ [The iterator category. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.pointer [*pointer]]]
+ [The type of the result of applying operator->() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.reference [*reference]]]
+ [The type of the result of applying operator*() to the iterator. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.ip__basic_resolver_iterator.value_type [*value_type]]]
+ [The type of the value pointed to by the iterator. ]
+
+ ]
+
+]
+
 [heading Member Functions]
 [table
   [[Name][Description]]
@@ -63959,7 +65365,7 @@
 [section:placeholders__iterator placeholders::iterator]
 
 [indexterm1 placeholders::iterator]
-An argument placeholder, for use with boost::bind(), that corresponds to the iterator argument of a handler for asynchronous functions such as boost::asio::basic\_resolver::resolve.
+An argument placeholder, for use with boost::bind(), that corresponds to the iterator argument of a handler for asynchronous functions such as boost::asio::basic\_resolver::async\_resolve.
 
 
   unspecified iterator;
@@ -63975,6 +65381,26 @@
 [endsect]
 
 
+
+[section:placeholders__signal_number placeholders::signal_number]
+
+[indexterm1 placeholders::signal_number]
+An argument placeholder, for use with boost::bind(), that corresponds to the signal\_number argument of a handler for asynchronous functions such as `boost::asio::signal_set::async_wait`.
+
+
+ unspecified signal_number;
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/placeholders.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
 [section:posix__basic_descriptor posix::basic_descriptor]
 
 
@@ -73761,6 +75187,464 @@
 
 [endsect]
 
+
+[section:signal_set signal_set]
+
+[indexterm1 signal_set]
+Typedef for the typical usage of a signal set.
+
+
+ typedef basic_signal_set signal_set;
+
+
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.basic_signal_set.implementation_type [*implementation_type]]]
+ [The underlying implementation type of I/O object. ]
+
+ ]
+
+ [
+
+ [[link boost_asio.reference.basic_signal_set.service_type [*service_type]]]
+ [The type of the service that will be used to provide I/O operations. ]
+
+ ]
+
+]
+
+[heading Member Functions]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.add [*add]]]
+ [Add a signal to a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.async_wait [*async_wait]]]
+ [Start an asynchronous operation to wait for a signal to be delivered. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.basic_signal_set [*basic_signal_set]]]
+ [Construct a signal set without adding any signals.
+
+ Construct a signal set and add one signal.
+
+ Construct a signal set and add two signals.
+
+ Construct a signal set and add three signals. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.cancel [*cancel]]]
+ [Cancel all operations associated with the signal set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.clear [*clear]]]
+ [Remove all signals from a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.get_io_service [*get_io_service]]]
+ [Get the io_service associated with the object. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.remove [*remove]]]
+ [Remove a signal from a signal_set. ]
+ ]
+
+]
+
+[heading Protected Data Members]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.implementation [*implementation]]]
+ [The underlying implementation of the I/O object. ]
+ ]
+
+ [
+ [[link boost_asio.reference.basic_signal_set.service [*service]]]
+ [The service associated with the I/O object. ]
+ ]
+
+]
+
+The [link boost_asio.reference.basic_signal_set `basic_signal_set`] class template provides the ability to perform an asynchronous wait for one or more signals to occur.
+
+Most applications will use the `boost::asio::signal_set` typedef.
+
+
+[heading Thread Safety]
+
+[*Distinct] [*objects:] Safe.
+
+[*Shared] [*objects:] Unsafe.
+
+
+[heading Example]
+
+Performing an asynchronous wait:
+
+ void handler(
+ const boost::system::error_code& error,
+ int signal_number)
+ {
+ if (!error)
+ {
+ // A signal occurred.
+ }
+ }
+
+ ...
+
+ // Construct a signal set registered for process termination.
+ boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
+
+ // Start an asynchronous wait for one of the signals to occur.
+ signals.async_wait(handler);
+
+
+
+
+
+[heading Queueing of signal notifications]
+
+
+
+If a signal is registered with a signal\_set, and the signal occurs when there are no waiting handlers, then the signal notification is queued. The next async\_wait operation on that signal\_set will dequeue the notification. If multiple notifications are queued, subsequent async\_wait operations dequeue them one at a time. Signal notifications are dequeued in order of ascending signal number.
+
+If a signal number is removed from a signal\_set (using the `remove` or `erase` member functions) then any queued notifications for that signal are discarded.
+
+
+[heading Multiple registration of signals]
+
+
+
+The same signal number may be registered with different signal\_set objects. When the signal occurs, one handler is called for each signal\_set object.
+
+Note that multiple registration only works for signals that are registered using Asio. The application must not also register a signal handler using functions such as `signal()` or `sigaction()`.
+
+
+[heading Signal masking on POSIX platforms]
+
+
+
+POSIX allows signals to be blocked using functions such as `sigprocmask()` and `pthread_sigmask()`. For signals to be delivered, programs must ensure that any signals registered using signal\_set objects are unblocked in at least one thread.
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/signal_set.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+[section:signal_set_service signal_set_service]
+
+
+Default service implementation for a signal set.
+
+
+ class signal_set_service :
+ public io_service::service
+
+
+[heading Types]
+[table
+ [[Name][Description]]
+
+ [
+
+ [[link boost_asio.reference.signal_set_service.implementation_type [*implementation_type]]]
+ [The type of a signal set implementation. ]
+
+ ]
+
+]
+
+[heading Member Functions]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.signal_set_service.add [*add]]]
+ [Add a signal to a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.async_wait [*async_wait]]]
+ []
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.cancel [*cancel]]]
+ [Cancel all operations associated with the signal set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.clear [*clear]]]
+ [Remove all signals from a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.construct [*construct]]]
+ [Construct a new signal set implementation. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.destroy [*destroy]]]
+ [Destroy a signal set implementation. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.get_io_service [*get_io_service]]]
+ [Get the io_service object that owns the service. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.remove [*remove]]]
+ [Remove a signal to a signal_set. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.shutdown_service [*shutdown_service]]]
+ [Destroy all user-defined handler objects owned by the service. ]
+ ]
+
+ [
+ [[link boost_asio.reference.signal_set_service.signal_set_service [*signal_set_service]]]
+ [Construct a new signal set service for the specified io_service. ]
+ ]
+
+]
+
+[heading Data Members]
+[table
+ [[Name][Description]]
+
+ [
+ [[link boost_asio.reference.signal_set_service.id [*id]]]
+ [The unique service identifier. ]
+ ]
+
+]
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/signal_set_service.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[section:add signal_set_service::add]
+
+[indexterm2 add..signal_set_service]
+Add a signal to a signal\_set.
+
+
+ boost::system::error_code add(
+ implementation_type & impl,
+ int signal_number,
+ boost::system::error_code & ec);
+
+
+
+[endsect]
+
+
+
+[section:async_wait signal_set_service::async_wait]
+
+[indexterm2 async_wait..signal_set_service]
+
+ template<
+ typename ``[link boost_asio.reference.SignalHandler SignalHandler]``>
+ void async_wait(
+ implementation_type & impl,
+ SignalHandler handler);
+
+
+
+[endsect]
+
+
+
+[section:cancel signal_set_service::cancel]
+
+[indexterm2 cancel..signal_set_service]
+Cancel all operations associated with the signal set.
+
+
+ boost::system::error_code cancel(
+ implementation_type & impl,
+ boost::system::error_code & ec);
+
+
+
+[endsect]
+
+
+
+[section:clear signal_set_service::clear]
+
+[indexterm2 clear..signal_set_service]
+Remove all signals from a signal\_set.
+
+
+ boost::system::error_code clear(
+ implementation_type & impl,
+ boost::system::error_code & ec);
+
+
+
+[endsect]
+
+
+
+[section:construct signal_set_service::construct]
+
+[indexterm2 construct..signal_set_service]
+Construct a new signal set implementation.
+
+
+ void construct(
+ implementation_type & impl);
+
+
+
+[endsect]
+
+
+
+[section:destroy signal_set_service::destroy]
+
+[indexterm2 destroy..signal_set_service]
+Destroy a signal set implementation.
+
+
+ void destroy(
+ implementation_type & impl);
+
+
+
+[endsect]
+
+
+
+[section:get_io_service signal_set_service::get_io_service]
+
+
+['Inherited from io_service.]
+
+[indexterm2 get_io_service..signal_set_service]
+Get the [link boost_asio.reference.io_service `io_service`] object that owns the service.
+
+
+ boost::asio::io_service & get_io_service();
+
+
+
+[endsect]
+
+
+
+[section:id signal_set_service::id]
+
+[indexterm2 id..signal_set_service]
+The unique service identifier.
+
+
+ static boost::asio::io_service::id id;
+
+
+
+[endsect]
+
+
+
+[section:implementation_type signal_set_service::implementation_type]
+
+[indexterm2 implementation_type..signal_set_service]
+The type of a signal set implementation.
+
+
+ typedef implementation_defined implementation_type;
+
+
+
+[heading Requirements]
+
+[*Header: ][^boost/asio/signal_set_service.hpp]
+
+[*Convenience header: ][^boost/asio.hpp]
+
+
+[endsect]
+
+
+
+[section:remove signal_set_service::remove]
+
+[indexterm2 remove..signal_set_service]
+Remove a signal to a signal\_set.
+
+
+ boost::system::error_code remove(
+ implementation_type & impl,
+ int signal_number,
+ boost::system::error_code & ec);
+
+
+
+[endsect]
+
+
+
+[section:shutdown_service signal_set_service::shutdown_service]
+
+[indexterm2 shutdown_service..signal_set_service]
+Destroy all user-defined handler objects owned by the service.
+
+
+ virtual void shutdown_service();
+
+
+
+[endsect]
+
+
+
+[section:signal_set_service signal_set_service::signal_set_service]
+
+[indexterm2 signal_set_service..signal_set_service]
+Construct a new signal set service for the specified [link boost_asio.reference.io_service `io_service`].
+
+
+ signal_set_service(
+ boost::asio::io_service & io_service);
+
+
+
+[endsect]
+
+
+
+[endsect]
+
 [section:socket_acceptor_service socket_acceptor_service]
 
 

Modified: trunk/libs/asio/doc/reference.xsl
==============================================================================
--- trunk/libs/asio/doc/reference.xsl (original)
+++ trunk/libs/asio/doc/reference.xsl 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -70,6 +70,8 @@
 [include requirements/Service.qbk]
 [include requirements/SettableSerialPortOption.qbk]
 [include requirements/SettableSocketOption.qbk]
+[include requirements/SignalHandler.qbk]
+[include requirements/SignalSetService.qbk]
 [include requirements/SocketAcceptorService.qbk]
 [include requirements/SocketService.qbk]
 [include requirements/StreamDescriptorService.qbk]

Added: trunk/libs/asio/doc/requirements/SignalHandler.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/asio/doc/requirements/SignalHandler.qbk 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,54 @@
+[/
+ / Copyright (c) 2003-2011 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)
+ /]
+
+[section:SignalHandler Signal handler requirements]
+
+A signal handler must meet the requirements for a [link
+boost_asio.reference.Handler handler]. A value `h` of a signal handler class
+should work correctly in the expression `h(ec, n)`, where `ec` is an lvalue of
+type `const error_code` and `n` is an lvalue of type `const int`.
+
+[heading Examples]
+
+A free function as a signal handler:
+
+ void signal_handler(
+ const boost::system::error_code& ec,
+ int signal_number)
+ {
+ ...
+ }
+
+A signal handler function object:
+
+ struct signal_handler
+ {
+ ...
+ void operator()(
+ const boost::system::error_code& ec,
+ int signal_number)
+ {
+ ...
+ }
+ ...
+ };
+
+A non-static class member function adapted to a signal handler using `bind()`:
+
+ void my_class::signal_handler(
+ const boost::system::error_code& ec,
+ int signal_number)
+ {
+ ...
+ }
+ ...
+ my_signal_set.async_wait(
+ boost::bind(&my_class::signal_handler,
+ this, boost::asio::placeholders::error,
+ boost::asio::placeholders::signal_number));
+
+[endsect]

Added: trunk/libs/asio/doc/requirements/SignalSetService.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/asio/doc/requirements/SignalSetService.qbk 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,91 @@
+[/
+ / Copyright (c) 2003-2011 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)
+ /]
+
+[section:SignalSetService Signal set service requirements]
+
+A signal set service must meet the requirements for an [link
+boost_asio.reference.IoObjectService I/O object service], as well as the
+additional requirements listed below.
+
+In the table below, `X` denotes a signal set service class, `a` denotes a value
+of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` denotes
+a value of type `error_code`, `n` denotes a value of type `int`, and `sh`
+denotes a value meeting [link boost_asio.reference.SignalHandler `SignalHandler`]
+requirements.
+
+[table SignalSetService requirements
+ [[expression] [return type] [assertion/note\npre/post-condition]]
+ [
+ [`a.construct(b);`]
+ []
+ [
+ From [link boost_asio.reference.IoObjectService IoObjectService]
+ requirements.\n
+ ]
+ ]
+ [
+ [`a.destroy(b);`]
+ []
+ [
+ From [link boost_asio.reference.IoObjectService IoObjectService]
+ requirements. Implicitly clears the registered signals as if by calling
+ `a.clear(b, ec)`, then implicitly cancels outstanding asynchronous
+ operations as if by calling `a.cancel(b, ec)`.
+ ]
+ ]
+ [
+ [``
+ a.add(b, n, ec);
+ ``]
+ [`error_code`]
+ [
+ ]
+ ]
+ [
+ [``
+ a.remove(b, n, ec);
+ ``]
+ [`error_code`]
+ [
+ ]
+ ]
+ [
+ [``
+ a.clear(b, ec);
+ ``]
+ [`error_code`]
+ [
+ ]
+ ]
+ [
+ [``
+ a.cancel(b, ec);
+ ``]
+ [`error_code`]
+ [
+ ]
+ ]
+ [
+ [`a.async_wait(b, sh);`]
+ [`void`]
+ [
+ pre: `a.is_open(b)`.\n
+ \n
+ Initiates an asynchronous operation to wait for the delivery of one of the
+ signals registered for the signal set `b`. The operation is performed via
+ the `io_service` object `a.get_io_service()` and behaves according to
+ [link boost_asio.reference.asynchronous_operations asynchronous operation]
+ requirements.\n
+ \n
+ If the operation completes successfully, the `SignalHandler` object
+ `sh` is invoked with the number identifying the delivered signal. Otherwise
+ it is invoked with `0`.
+ ]
+ ]
+]
+
+[endsect]

Modified: trunk/libs/asio/example/http/server/Jamfile
==============================================================================
--- trunk/libs/asio/example/http/server/Jamfile (original)
+++ trunk/libs/asio/example/http/server/Jamfile 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -25,13 +25,12 @@
     <lib>@boost/libs/system/build/boost_system
     connection.cpp
     connection_manager.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
   : <include>$(BOOST_ROOT)
     <include>../../../../..
     <define>BOOST_ALL_NO_LIB=1

Modified: trunk/libs/asio/example/http/server/Jamfile.v2
==============================================================================
--- trunk/libs/asio/example/http/server/Jamfile.v2 (original)
+++ trunk/libs/asio/example/http/server/Jamfile.v2 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -25,13 +25,12 @@
 exe server
   : connection.cpp
     connection_manager.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
     /boost/system//boost_system
     /boost/thread//boost_thread
   : <define>BOOST_ALL_NO_LIB=1

Added: trunk/libs/asio/example/http/server/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/http/server/main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,44 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#include <iostream>
+#include <string>
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include "server.hpp"
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 80 .\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 80 .\n";
+ return 1;
+ }
+
+ // Initialise the server.
+ http::server::server s(argv[1], argv[2], argv[3]);
+
+ // Run the server until stopped.
+ s.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}

Deleted: trunk/libs/asio/example/http/server/posix_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server/posix_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,73 +0,0 @@
-//
-// posix_main.cpp
-// ~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
-#include <boost/bind.hpp>
-#include "server.hpp"
-
-#if !defined(_WIN32)
-
-#include <pthread.h>
-#include <signal.h>
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 4)
- {
- std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " receiver 0.0.0.0 80 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " receiver 0::0 80 .\n";
- return 1;
- }
-
- // Block all signals for background thread.
- sigset_t new_mask;
- sigfillset(&new_mask);
- sigset_t old_mask;
- pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
-
- // Run server in background thread.
- http::server::server s(argv[1], argv[2], argv[3]);
- boost::thread t(boost::bind(&http::server::server::run, &s));
-
- // Restore previous signals.
- pthread_sigmask(SIG_SETMASK, &old_mask, 0);
-
- // Wait for signal indicating time to shut down.
- sigset_t wait_mask;
- sigemptyset(&wait_mask);
- sigaddset(&wait_mask, SIGINT);
- sigaddset(&wait_mask, SIGQUIT);
- sigaddset(&wait_mask, SIGTERM);
- pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
- int sig = 0;
- sigwait(&wait_mask, &sig);
-
- // Stop the server.
- s.stop();
- t.join();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // !defined(_WIN32)

Modified: trunk/libs/asio/example/http/server/server.cpp
==============================================================================
--- trunk/libs/asio/example/http/server/server.cpp (original)
+++ trunk/libs/asio/example/http/server/server.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -10,6 +10,7 @@
 
 #include "server.hpp"
 #include <boost/bind.hpp>
+#include <signal.h>
 
 namespace http {
 namespace server {
@@ -17,12 +18,23 @@
 server::server(const std::string& address, const std::string& port,
     const std::string& doc_root)
   : io_service_(),
+ signals_(io_service_),
     acceptor_(io_service_),
     connection_manager_(),
     new_connection_(new connection(io_service_,
           connection_manager_, request_handler_)),
     request_handler_(doc_root)
 {
+ // Register to handle the signals that indicate when the server should exit.
+ // It is safe to register for the same signal multiple times in a program,
+ // provided all registration for the specified signal is made through Asio.
+ signals_.add(SIGINT);
+ signals_.add(SIGTERM);
+#if defined(SIGQUIT)
+ signals_.add(SIGQUIT);
+#endif // defined(SIGQUIT)
+ signals_.async_wait(boost::bind(&server::handle_stop, this));
+
   // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
   boost::asio::ip::tcp::resolver resolver(io_service_);
   boost::asio::ip::tcp::resolver::query query(address, port);

Modified: trunk/libs/asio/example/http/server/server.hpp
==============================================================================
--- trunk/libs/asio/example/http/server/server.hpp (original)
+++ trunk/libs/asio/example/http/server/server.hpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -47,6 +47,9 @@
   /// The io_service used to perform asynchronous operations.
   boost::asio::io_service io_service_;
 
+ /// The signal_set is used to register for process termination notifications.
+ boost::asio::signal_set signals_;
+
   /// Acceptor used to listen for incoming connections.
   boost::asio::ip::tcp::acceptor acceptor_;
 

Deleted: trunk/libs/asio/example/http/server/win_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server/win_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,70 +0,0 @@
-//
-// win_main.cpp
-// ~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include "server.hpp"
-
-#if defined(_WIN32)
-
-boost::function0<void> console_ctrl_function;
-
-BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- console_ctrl_function();
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 4)
- {
- std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " http_server 0.0.0.0 80 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " http_server 0::0 80 .\n";
- return 1;
- }
-
- // Initialise server.
- http::server::server s(argv[1], argv[2], argv[3]);
-
- // Set console control handler to allow server to be stopped.
- console_ctrl_function = boost::bind(&http::server::server::stop, &s);
- SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
-
- // Run the server until stopped.
- s.run();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // defined(_WIN32)

Modified: trunk/libs/asio/example/http/server2/Jamfile
==============================================================================
--- trunk/libs/asio/example/http/server2/Jamfile (original)
+++ trunk/libs/asio/example/http/server2/Jamfile 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -25,13 +25,12 @@
     <lib>@boost/libs/system/build/boost_system
     connection.cpp
     io_service_pool.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
   : <include>$(BOOST_ROOT)
     <include>../../../../..
     <define>BOOST_ALL_NO_LIB=1

Modified: trunk/libs/asio/example/http/server2/Jamfile.v2
==============================================================================
--- trunk/libs/asio/example/http/server2/Jamfile.v2 (original)
+++ trunk/libs/asio/example/http/server2/Jamfile.v2 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -25,13 +25,12 @@
 exe server
   : connection.cpp
     io_service_pool.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
     /boost/system//boost_system
     /boost/thread//boost_thread
   : <define>BOOST_ALL_NO_LIB=1

Added: trunk/libs/asio/example/http/server2/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/http/server2/main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,46 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#include <iostream>
+#include <string>
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include "server.hpp"
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 80 .\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 80 .\n";
+ return 1;
+ }
+
+ // Initialise the server.
+ std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
+ http::server2::server s(argv[1], argv[2], argv[4], num_threads);
+
+ // Run the server until stopped.
+ s.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}

Deleted: trunk/libs/asio/example/http/server2/posix_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server2/posix_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,75 +0,0 @@
-//
-// posix_main.cpp
-// ~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
-#include <boost/bind.hpp>
-#include <boost/lexical_cast.hpp>
-#include "server.hpp"
-
-#if !defined(_WIN32)
-
-#include <pthread.h>
-#include <signal.h>
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 5)
- {
- std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " receiver 0.0.0.0 80 1 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " receiver 0::0 80 1 .\n";
- return 1;
- }
-
- // Block all signals for background thread.
- sigset_t new_mask;
- sigfillset(&new_mask);
- sigset_t old_mask;
- pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
-
- // Run server in background thread.
- std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
- http::server2::server s(argv[1], argv[2], argv[4], num_threads);
- boost::thread t(boost::bind(&http::server2::server::run, &s));
-
- // Restore previous signals.
- pthread_sigmask(SIG_SETMASK, &old_mask, 0);
-
- // Wait for signal indicating time to shut down.
- sigset_t wait_mask;
- sigemptyset(&wait_mask);
- sigaddset(&wait_mask, SIGINT);
- sigaddset(&wait_mask, SIGQUIT);
- sigaddset(&wait_mask, SIGTERM);
- pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
- int sig = 0;
- sigwait(&wait_mask, &sig);
-
- // Stop the server.
- s.stop();
- t.join();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // !defined(_WIN32)

Deleted: trunk/libs/asio/example/http/server2/win_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server2/win_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,72 +0,0 @@
-//
-// win_main.cpp
-// ~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/lexical_cast.hpp>
-#include "server.hpp"
-
-#if defined(_WIN32)
-
-boost::function0<void> console_ctrl_function;
-
-BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- console_ctrl_function();
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 5)
- {
- std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " http_server 0.0.0.0 80 1 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " http_server 0::0 80 1 .\n";
- return 1;
- }
-
- // Initialise server.
- std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
- http::server2::server s(argv[1], argv[2], argv[4], num_threads);
-
- // Set console control handler to allow server to be stopped.
- console_ctrl_function = boost::bind(&http::server2::server::stop, &s);
- SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
-
- // Run the server until stopped.
- s.run();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // defined(_WIN32)

Modified: trunk/libs/asio/example/http/server3/Jamfile
==============================================================================
--- trunk/libs/asio/example/http/server3/Jamfile (original)
+++ trunk/libs/asio/example/http/server3/Jamfile 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -24,13 +24,12 @@
   : <lib>@boost/libs/thread/build/boost_thread
     <lib>@boost/libs/system/build/boost_system
     connection.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
   : <include>$(BOOST_ROOT)
     <include>../../../../..
     <define>BOOST_ALL_NO_LIB=1

Modified: trunk/libs/asio/example/http/server3/Jamfile.v2
==============================================================================
--- trunk/libs/asio/example/http/server3/Jamfile.v2 (original)
+++ trunk/libs/asio/example/http/server3/Jamfile.v2 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -24,13 +24,12 @@
 
 exe server
   : connection.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_handler.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
     /boost/system//boost_system
     /boost/thread//boost_thread
   : <define>BOOST_ALL_NO_LIB=1

Added: trunk/libs/asio/example/http/server3/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/http/server3/main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,46 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#include <iostream>
+#include <string>
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include "server.hpp"
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 80 .\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 80 .\n";
+ return 1;
+ }
+
+ // Initialise the server.
+ std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
+ http::server3::server s(argv[1], argv[2], argv[4], num_threads);
+
+ // Run the server until stopped.
+ s.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}

Deleted: trunk/libs/asio/example/http/server3/posix_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server3/posix_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,75 +0,0 @@
-//
-// posix_main.cpp
-// ~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
-#include <boost/bind.hpp>
-#include <boost/lexical_cast.hpp>
-#include "server.hpp"
-
-#if !defined(_WIN32)
-
-#include <pthread.h>
-#include <signal.h>
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 5)
- {
- std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " receiver 0.0.0.0 80 1 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " receiver 0::0 80 1 .\n";
- return 1;
- }
-
- // Block all signals for background thread.
- sigset_t new_mask;
- sigfillset(&new_mask);
- sigset_t old_mask;
- pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
-
- // Run server in background thread.
- std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
- http::server3::server s(argv[1], argv[2], argv[4], num_threads);
- boost::thread t(boost::bind(&http::server3::server::run, &s));
-
- // Restore previous signals.
- pthread_sigmask(SIG_SETMASK, &old_mask, 0);
-
- // Wait for signal indicating time to shut down.
- sigset_t wait_mask;
- sigemptyset(&wait_mask);
- sigaddset(&wait_mask, SIGINT);
- sigaddset(&wait_mask, SIGQUIT);
- sigaddset(&wait_mask, SIGTERM);
- pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
- int sig = 0;
- sigwait(&wait_mask, &sig);
-
- // Stop the server.
- s.stop();
- t.join();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // !defined(_WIN32)

Deleted: trunk/libs/asio/example/http/server3/win_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server3/win_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,72 +0,0 @@
-//
-// win_main.cpp
-// ~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <string>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/lexical_cast.hpp>
-#include "server.hpp"
-
-#if defined(_WIN32)
-
-boost::function0<void> console_ctrl_function;
-
-BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- console_ctrl_function();
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 5)
- {
- std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " http_server 0.0.0.0 80 1 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " http_server 0::0 80 1 .\n";
- return 1;
- }
-
- // Initialise server.
- std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]);
- http::server3::server s(argv[1], argv[2], argv[4], num_threads);
-
- // Set console control handler to allow server to be stopped.
- console_ctrl_function = boost::bind(&http::server3::server::stop, &s);
- SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
-
- // Run the server until stopped.
- s.run();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // defined(_WIN32)

Modified: trunk/libs/asio/example/http/server4/Jamfile
==============================================================================
--- trunk/libs/asio/example/http/server4/Jamfile (original)
+++ trunk/libs/asio/example/http/server4/Jamfile 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -24,12 +24,11 @@
   : <lib>@boost/libs/thread/build/boost_thread
     <lib>@boost/libs/system/build/boost_system
     file_handler.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
   : <include>$(BOOST_ROOT)
     <include>../../../../..
     <define>BOOST_ALL_NO_LIB=1

Modified: trunk/libs/asio/example/http/server4/Jamfile.v2
==============================================================================
--- trunk/libs/asio/example/http/server4/Jamfile.v2 (original)
+++ trunk/libs/asio/example/http/server4/Jamfile.v2 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -24,12 +24,11 @@
 
 exe server
   : file_handler.cpp
+ main.cpp
     mime_types.cpp
- posix_main.cpp
     reply.cpp
     request_parser.cpp
     server.cpp
- win_main.cpp
     /boost/system//boost_system
     /boost/thread//boost_thread
   : <define>BOOST_ALL_NO_LIB=1

Added: trunk/libs/asio/example/http/server4/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/http/server4/main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,58 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#include <iostream>
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <signal.h>
+#include "server.hpp"
+#include "file_handler.hpp"
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 80 .\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 80 .\n";
+ return 1;
+ }
+
+ boost::asio::io_service io_service;
+
+ // Launch the initial server coroutine.
+ http::server4::server(io_service, argv[1], argv[2],
+ http::server4::file_handler(argv[3]))();
+
+ // Wait for signals indicating time to shut down.
+ boost::asio::signal_set signals(io_service);
+ signals.add(SIGINT);
+ signals.add(SIGTERM);
+#if defined(SIGQUIT)
+ signals.add(SIGQUIT);
+#endif // defined(SIGQUIT)
+ signals.async_wait(boost::bind(
+ &boost::asio::io_service::stop, &io_service));
+
+ // Run the server.
+ io_service.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}

Deleted: trunk/libs/asio/example/http/server4/posix_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server4/posix_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,78 +0,0 @@
-//
-// posix_main.cpp
-// ~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
-#include <boost/bind.hpp>
-#include "server.hpp"
-#include "file_handler.hpp"
-
-#if !defined(_WIN32)
-
-#include <pthread.h>
-#include <signal.h>
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 4)
- {
- std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " receiver 0.0.0.0 80 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " receiver 0::0 80 .\n";
- return 1;
- }
-
- boost::asio::io_service io_service;
-
- // Launch the initial server coroutine.
- http::server4::server(io_service, argv[1], argv[2],
- http::server4::file_handler(argv[3]))();
-
- // Block all signals for background thread.
- sigset_t new_mask;
- sigfillset(&new_mask);
- sigset_t old_mask;
- pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
-
- // Run server in background thread.
- boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
-
- // Restore previous signals.
- pthread_sigmask(SIG_SETMASK, &old_mask, 0);
-
- // Wait for signal indicating time to shut down.
- sigset_t wait_mask;
- sigemptyset(&wait_mask);
- sigaddset(&wait_mask, SIGINT);
- sigaddset(&wait_mask, SIGQUIT);
- sigaddset(&wait_mask, SIGTERM);
- pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
- int sig = 0;
- sigwait(&wait_mask, &sig);
-
- // Stop the server and wait for the background thread to exit.
- io_service.stop();
- t.join();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // !defined(_WIN32)

Deleted: trunk/libs/asio/example/http/server4/win_main.cpp
==============================================================================
--- trunk/libs/asio/example/http/server4/win_main.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
+++ (empty file)
@@ -1,74 +0,0 @@
-//
-// win_main.cpp
-// ~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2011 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)
-//
-
-#include <iostream>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include "server.hpp"
-#include "file_handler.hpp"
-
-#if defined(_WIN32)
-
-boost::function0<void> console_ctrl_function;
-
-BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- console_ctrl_function();
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-int main(int argc, char* argv[])
-{
- try
- {
- // Check command line arguments.
- if (argc != 4)
- {
- std::cerr << "Usage: http_server <address> <port> <doc_root>\n";
- std::cerr << " For IPv4, try:\n";
- std::cerr << " http_server 0.0.0.0 80 .\n";
- std::cerr << " For IPv6, try:\n";
- std::cerr << " http_server 0::0 80 .\n";
- return 1;
- }
-
- boost::asio::io_service io_service;
-
- // Launch the initial server coroutine.
- http::server4::server(io_service, argv[1], argv[2],
- http::server4::file_handler(argv[3]))();
-
- // Set console control handler to allow server to be stopped.
- console_ctrl_function = boost::bind(
- &boost::asio::io_service::stop, &io_service);
- SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
-
- // Run the server until stopped.
- io_service.run();
- }
- catch (std::exception& e)
- {
- std::cerr << "exception: " << e.what() << "\n";
- }
-
- return 0;
-}
-
-#endif // defined(_WIN32)

Modified: trunk/libs/asio/test/Jamfile
==============================================================================
--- trunk/libs/asio/test/Jamfile (original)
+++ trunk/libs/asio/test/Jamfile 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -43,8 +43,10 @@
   [ run basic_deadline_timer.cpp <template>asio_unit_test ]
   [ run basic_raw_socket.cpp <template>asio_unit_test ]
   [ run basic_seq_packet_socket.cpp <template>asio_unit_test ]
+ [ run basic_signal_set.cpp <template>asio_unit_test ]
   [ run basic_socket_acceptor.cpp <template>asio_unit_test ]
   [ run basic_stream_socket.cpp <template>asio_unit_test ]
+ [ run basic_streambuf.cpp <template>asio_unit_test ]
   [ run buffer.cpp <template>asio_unit_test ]
   [ run buffered_read_stream.cpp <template>asio_unit_test ]
   [ run buffered_stream.cpp <template>asio_unit_test ]
@@ -90,10 +92,13 @@
   [ run read_at.cpp <template>asio_unit_test ]
   [ run read_until.cpp <template>asio_unit_test ]
   [ run seq_packet_socket_service.cpp <template>asio_unit_test ]
+ [ run signal_set.cpp <template>asio_unit_test ]
+ [ run signal_set_service.cpp <template>asio_unit_test ]
   [ run socket_acceptor_service.cpp <template>asio_unit_test ]
   [ run socket_base.cpp <template>asio_unit_test ]
   [ run strand.cpp <template>asio_unit_test ]
   [ run stream_socket_service.cpp <template>asio_unit_test ]
+ [ run streambuf.cpp <template>asio_unit_test ]
   [ run time_traits.cpp <template>asio_unit_test ]
   [ run windows/basic_handle.cpp <template>asio_unit_test ]
   [ run windows/basic_random_access_handle.cpp <template>asio_unit_test ]

Modified: trunk/libs/asio/test/Jamfile.v2
==============================================================================
--- trunk/libs/asio/test/Jamfile.v2 (original)
+++ trunk/libs/asio/test/Jamfile.v2 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -69,10 +69,14 @@
   [ link basic_raw_socket.cpp : $(USE_SELECT) : basic_raw_socket_select ]
   [ link basic_seq_packet_socket.cpp ]
   [ link basic_seq_packet_socket.cpp : $(USE_SELECT) : basic_seq_packet_socket_select ]
+ [ link basic_signal_set.cpp ]
+ [ link basic_signal_set.cpp : $(USE_SELECT) : basic_signal_set_select ]
   [ link basic_socket_acceptor.cpp ]
   [ link basic_socket_acceptor.cpp : $(USE_SELECT) : basic_socket_acceptor_select ]
   [ link basic_stream_socket.cpp ]
   [ link basic_stream_socket.cpp : $(USE_SELECT) : basic_stream_socket_select ]
+ [ link basic_streambuf.cpp ]
+ [ link basic_streambuf.cpp : $(USE_SELECT) : basic_streambuf_select ]
   [ run buffer.cpp ]
   [ run buffer.cpp : : : $(USE_SELECT) : buffer_select ]
   [ run buffered_read_stream.cpp ]
@@ -163,6 +167,10 @@
   [ run read_until.cpp : : : $(USE_SELECT) : read_until_select ]
   [ link seq_packet_socket_service.cpp ]
   [ link seq_packet_socket_service.cpp : $(USE_SELECT) : seq_packet_socket_service_select ]
+ [ run signal_set.cpp ]
+ [ run signal_set.cpp : : : $(USE_SELECT) : signal_set_select ]
+ [ link signal_set_service.cpp ]
+ [ link signal_set_service.cpp : $(USE_SELECT) : signal_set_service_select ]
   [ link socket_acceptor_service.cpp ]
   [ link socket_acceptor_service.cpp : $(USE_SELECT) : socket_acceptor_service_select ]
   [ run socket_base.cpp ]
@@ -171,6 +179,8 @@
   [ run strand.cpp : : : $(USE_SELECT) : strand_select ]
   [ link stream_socket_service.cpp ]
   [ link stream_socket_service.cpp : $(USE_SELECT) : stream_socket_service_select ]
+ [ run streambuf.cpp ]
+ [ run streambuf.cpp : : : $(USE_SELECT) : streambuf_select ]
   [ link time_traits.cpp ]
   [ link time_traits.cpp : $(USE_SELECT) : time_traits_select ]
   [ link windows/basic_handle.cpp : : windows_basic_handle ]

Added: trunk/libs/asio/test/basic_signal_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/basic_signal_set.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,26 @@
+//
+// basic_signal_set.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_signal_set.hpp>
+
+#include "unit_test.hpp"
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+ test_suite* test = BOOST_TEST_SUITE("basic_signal_set");
+ test->add(BOOST_TEST_CASE(&null_test));
+ return test;
+}

Added: trunk/libs/asio/test/basic_streambuf.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/basic_streambuf.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,26 @@
+//
+// basic_streambuf.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_streambuf.hpp>
+
+#include "unit_test.hpp"
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+ test_suite* test = BOOST_TEST_SUITE("basic_streambuf");
+ test->add(BOOST_TEST_CASE(&null_test));
+ return test;
+}

Added: trunk/libs/asio/test/signal_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/signal_set.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,86 @@
+//
+// signal_set.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/signal_set.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include "unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// signal_set_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// signal_set compile and link correctly. Runtime failures are ignored.
+
+namespace signal_set_compile {
+
+void signal_handler(const boost::system::error_code&, int)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+
+ try
+ {
+ io_service ios;
+ boost::system::error_code ec;
+
+ // basic_signal_set constructors.
+
+ signal_set set1(ios);
+ signal_set set2(ios, 1);
+ signal_set set3(ios, 1, 2);
+ signal_set set4(ios, 1, 2, 3);
+
+ // basic_io_object functions.
+
+ io_service& ios_ref = set1.get_io_service();
+ (void)ios_ref;
+
+ // basic_signal_set functions.
+
+ set1.add(1);
+ set1.add(1, ec);
+
+ set1.remove(1);
+ set1.remove(1, ec);
+
+ set1.clear();
+ set1.clear(ec);
+
+ set1.cancel();
+ set1.cancel(ec);
+
+ set1.async_wait(signal_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace signal_set_compile
+
+//------------------------------------------------------------------------------
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+ test_suite* test = BOOST_TEST_SUITE("signal_set");
+ test->add(BOOST_TEST_CASE(&signal_set_compile::test));
+ return test;
+}

Added: trunk/libs/asio/test/signal_set_service.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/signal_set_service.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,26 @@
+//
+// signal_set_service.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/signal_set_service.hpp>
+
+#include "unit_test.hpp"
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+ test_suite* test = BOOST_TEST_SUITE("signal_set_service");
+ test->add(BOOST_TEST_CASE(&null_test));
+ return test;
+}

Added: trunk/libs/asio/test/streambuf.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/streambuf.cpp 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,63 @@
+//
+// streambuf.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/streambuf.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include "unit_test.hpp"
+
+void streambuf_test()
+{
+ boost::asio::streambuf sb;
+
+ sb.sputn("abcd", 4);
+
+ BOOST_CHECK(sb.size() == 4);
+
+ for (int i = 0; i < 100; ++i)
+ {
+ sb.consume(3);
+
+ BOOST_CHECK(sb.size() == 1);
+
+ char buf[1];
+ sb.sgetn(buf, 1);
+
+ BOOST_CHECK(sb.size() == 0);
+
+ sb.sputn("ab", 2);
+
+ BOOST_CHECK(sb.size() == 2);
+
+ boost::asio::buffer_copy(sb.prepare(10), boost::asio::buffer("cd", 2));
+ sb.commit(2);
+
+ BOOST_CHECK(sb.size() == 4);
+ }
+
+ BOOST_CHECK(sb.size() == 4);
+
+ sb.consume(4);
+
+ BOOST_CHECK(sb.size() == 0);
+}
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+ test_suite* test = BOOST_TEST_SUITE("streambuf");
+ test->add(BOOST_TEST_CASE(&streambuf_test));
+ return test;
+}

Added: trunk/libs/asio/tools/handlerviz.pl
==============================================================================
--- (empty file)
+++ trunk/libs/asio/tools/handlerviz.pl 2011-02-22 20:42:40 EST (Tue, 22 Feb 2011)
@@ -0,0 +1,299 @@
+#!/usr/bin/perl -w
+#
+# handlerviz.pl
+# ~~~~~~~~~~~~~
+#
+# A visualisation tool for post-processing the debug output generated by
+# Asio-based programs. Programs write this output to the standard error stream
+# when compiled with the define `BOOST_ASIO_ENABLE_HANDLER_TRACKING'.
+#
+# This tool generates output intended for use with the GraphViz tool `dot'. For
+# example, to convert output to a PNG image, use:
+#
+# perl handlerviz.pl < output.txt | dot -Tpng > output.png
+#
+# To convert to a PDF file, use:
+#
+# perl handlerviz.pl < output.txt | dot -Tpdf > output.pdf
+#
+# Copyright (c) 2011 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)
+#
+
+use strict;
+
+my %nodes = ();
+my @edges = ();
+my %anon_nodes = ();
+my $anon_id = 0;
+my %all_nodes = ();
+
+#-------------------------------------------------------------------------------
+# Parse the debugging output and populate the nodes and edges.
+
+sub parse_debug_output()
+{
+ while (my $line = <>)
+ {
+ chomp($line);
+
+ if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/)
+ {
+ my $timestamp = $1;
+ my $action = $2;
+ my $description = $3;
+
+ # Handler creation.
+ if ($action =~ /^([0-9]+)\*([0-9]+)$/)
+ {
+ my $begin = $1;
+ my $end = $2;
+ my $label = $description;
+ $label =~ s/\./\\n/g;
+
+ if ($begin eq "0")
+ {
+ $begin = "a" . $anon_id++;
+ $anon_nodes{$begin} = $timestamp;
+ $all_nodes{"$timestamp-$begin"} = $begin;
+ }
+
+ my %edge = ( begin=>$begin, end=>$end, label=>$label );
+ push(@edges, \%edge);
+ }
+
+ # Begin handler invocation.
+ elsif ($action =~ /^>([0-9]+)$/)
+ {
+ my %new_node = ( label=>$description, entry=>$timestamp );
+ $new_node{content} = ();
+ $nodes{$1} = \%new_node;
+ $all_nodes{"$timestamp-$1"} = $1;
+ }
+
+ # End handler invocation.
+ elsif ($action =~ /^<([0-9]+)$/)
+ {
+ $nodes{$1}->{exit} = $timestamp;
+ }
+
+ # Handler threw exception.
+ elsif ($action =~ /^!([0-9]+)$/)
+ {
+ push(@{$nodes{$1}->{content}}, "exception");
+ }
+
+ # Handler was destroyed without being invoked.
+ elsif ($action =~ /^~([0-9]+)$/)
+ {
+ my %new_node = ( label=>"$timestamp destroyed" );
+ $new_node{content} = ();
+ $nodes{$1} = \%new_node;
+ $all_nodes{"$timestamp-$1"} = $1;
+ }
+
+ # Handler performed some operation.
+ elsif ($action =~ /^([0-9]+)$/)
+ {
+ if ($1 eq "0")
+ {
+ my $id = "a" . $anon_id++;
+ $anon_nodes{$id} = "$timestamp\\l$description";
+ $all_nodes{"$timestamp-$id"} = $id;
+ }
+ else
+ {
+ push(@{$nodes{$1}->{content}}, "$description");
+ }
+ }
+ }
+ }
+}
+
+#-------------------------------------------------------------------------------
+# Helper function to convert a string to escaped HTML text.
+
+sub escape($)
+{
+ my $text = shift;
+ $text =~ s/&/\&amp\;/g;
+ $text =~ s/</\&lt\;/g;
+ $text =~ s/>/\&gt\;/g;
+ $text =~ s/\t/ /g;
+ return $text;
+}
+
+#-------------------------------------------------------------------------------
+# Templates for dot output.
+
+my $graph_header = <<"EOF";
+/* Generated by asioviz.pl */
+digraph G
+{
+graph [ nodesep="1" ];
+node [ shape="box", fontsize="9" ];
+edge [ arrowtail="dot", fontsize="9" ];
+EOF
+
+my $graph_footer = <<"EOF";
+}
+EOF
+
+my $node_header = <<"EOF";
+"%name%"
+[
+label=<<table border="0" cellspacing="0">
+<tr><td align="left" bgcolor="gray" border="0">%label%</td></tr>
+EOF
+
+my $node_footer = <<"EOF";
+</table>>
+]
+EOF
+
+my $node_content = <<"EOF";
+<tr><td align="left" bgcolor="white" border="0">
+<font face="mono" point-size="9">%content%</font>
+</td></tr>
+EOF
+
+my $anon_nodes_header = <<"EOF";
+{
+node [ shape="record" ];
+EOF
+
+my $anon_nodes_footer = <<"EOF";
+}
+EOF
+
+my $anon_node = <<"EOF";
+"%name%" [ label="%label%", color="gray" ];
+EOF
+
+my $edges_header = <<"EOF";
+{
+edge [ style="dashed", arrowhead="open", weight="100" ];
+EOF
+
+my $edges_footer = <<"EOF";
+}
+EOF
+
+my $edge = <<"EOF";
+"%begin%" -> "%end%" [ label="%label%" ]
+EOF
+
+my $node_order_header = <<"EOF";
+{
+edge [ style="invis", weight="1" ];
+EOF
+
+my $node_order_footer = <<"EOF";
+}
+EOF
+
+my $node_order = <<"EOF";
+"%begin%" -> "%end%"
+EOF
+
+#-------------------------------------------------------------------------------
+# Generate dot output from the nodes and edges.
+
+sub print_nodes()
+{
+ foreach my $name (sort keys %nodes)
+ {
+ my $node = $nodes{$name};
+ my $entry = $node->{entry};
+ my $exit = $node->{exit};
+ my $label = escape($node->{label});
+ my $header = $node_header;
+ $header =~ s/%name%/$name/g;
+ $header =~ s/%label%/$label/g;
+ print($header);
+
+ my $line = $node_content;
+ my $content = $entry . " + " . sprintf("%.6f", $exit - $entry) . "s";
+ $line =~ s/%content%/$content/g;
+ print($line);
+
+ foreach my $content (@{$node->{content}})
+ {
+ $content = escape($content);
+ $content = " " if length($content) == 0;
+ my $line = $node_content;
+ $line =~ s/%content%/$content/g;
+ print($line);
+ }
+
+ print($node_footer);
+ }
+}
+
+sub print_anon_nodes()
+{
+ print($anon_nodes_header);
+ foreach my $name (sort keys %anon_nodes)
+ {
+ my $label = $anon_nodes{$name};
+ my $line = $anon_node;
+ $line =~ s/%name%/$name/g;
+ $line =~ s/%label%/$label/g;
+ print($line);
+ }
+ print($edges_footer);
+}
+
+sub print_edges()
+{
+ print($edges_header);
+ foreach my $e (@edges)
+ {
+ my $begin = $e->{begin};
+ my $end = $e->{end};
+ my $label = $e->{label};
+ my $line = $edge;
+ $line =~ s/%begin%/$begin/g;
+ $line =~ s/%end%/$end/g;
+ $line =~ s/%label%/$label/g;
+ print($line);
+ }
+ print($edges_footer);
+}
+
+sub print_node_order()
+{
+ my $prev = "";
+ print($node_order_header);
+ foreach my $name (sort keys %all_nodes)
+ {
+ if ($prev ne "")
+ {
+ my $begin = $prev;
+ my $end = $all_nodes{$name};
+ my $line = $node_order;
+ $line =~ s/%begin%/$begin/g;
+ $line =~ s/%end%/$end/g;
+ print($line);
+ }
+ $prev = $all_nodes{$name};
+ }
+ print($node_order_footer);
+}
+
+sub generate_dot()
+{
+ print($graph_header);
+ print_nodes();
+ print_anon_nodes();
+ print_edges();
+ print_node_order();
+ print($graph_footer);
+}
+
+#-------------------------------------------------------------------------------
+
+parse_debug_output();
+generate_dot();


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