$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r76397 - in trunk: boost boost/asio/detail boost/asio/detail/impl boost/asio/impl boost/asio/windows libs/asio/doc/overview libs/asio/test libs/asio/test/windows
From: chris_at_[hidden]
Date: 2012-01-10 04:58:08
Author: chris_kohlhoff
Date: 2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
New Revision: 76397
URL: http://svn.boost.org/trac/boost/changeset/76397
Log:
Added object_handle support.
Added:
   trunk/boost/asio/detail/impl/win_object_handle_service.ipp   (contents, props changed)
   trunk/boost/asio/detail/wait_op.hpp   (contents, props changed)
   trunk/boost/asio/detail/win_object_handle_service.hpp   (contents, props changed)
   trunk/boost/asio/windows/basic_object_handle.hpp   (contents, props changed)
   trunk/boost/asio/windows/object_handle.hpp   (contents, props changed)
   trunk/boost/asio/windows/object_handle_service.hpp   (contents, props changed)
   trunk/libs/asio/test/windows/basic_object_handle.cpp   (contents, props changed)
   trunk/libs/asio/test/windows/object_handle.cpp   (contents, props changed)
   trunk/libs/asio/test/windows/object_handle_service.cpp   (contents, props changed)
Removed:
   trunk/boost/asio/detail/timer_op.hpp
Text files modified: 
   trunk/boost/asio.hpp                                 |     3 ++                                      
   trunk/boost/asio/detail/config.hpp                   |     7 ++++++                                  
   trunk/boost/asio/detail/deadline_timer_service.hpp   |     2                                         
   trunk/boost/asio/detail/dev_poll_reactor.hpp         |     4 +-                                      
   trunk/boost/asio/detail/epoll_reactor.hpp            |     4 +-                                      
   trunk/boost/asio/detail/impl/dev_poll_reactor.hpp    |     2                                         
   trunk/boost/asio/detail/impl/epoll_reactor.hpp       |     2                                         
   trunk/boost/asio/detail/impl/kqueue_reactor.hpp      |     2                                         
   trunk/boost/asio/detail/impl/select_reactor.hpp      |     2                                         
   trunk/boost/asio/detail/impl/timer_queue_ptime.ipp   |     2                                         
   trunk/boost/asio/detail/impl/win_iocp_io_service.hpp |     2                                         
   trunk/boost/asio/detail/kqueue_reactor.hpp           |     4 +-                                      
   trunk/boost/asio/detail/select_reactor.hpp           |     4 +-                                      
   trunk/boost/asio/detail/timer_queue.hpp              |     8 +++---                                  
   trunk/boost/asio/detail/timer_queue_ptime.hpp        |     2                                         
   trunk/boost/asio/detail/wait_handler.hpp             |     7 +++--                                   
   trunk/boost/asio/detail/win_iocp_io_service.hpp      |     8 +++---                                  
   trunk/boost/asio/impl/src.hpp                        |     1                                         
   trunk/libs/asio/doc/overview/windows.qbk             |    41 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/asio/test/Jamfile.v2                      |     6 +++++                                   
   20 files changed, 86 insertions(+), 27 deletions(-)
Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp	(original)
+++ trunk/boost/asio.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -96,8 +96,11 @@
 #include <boost/asio/wait_traits.hpp>
 #include <boost/asio/waitable_timer_service.hpp>
 #include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/basic_object_handle.hpp>
 #include <boost/asio/windows/basic_random_access_handle.hpp>
 #include <boost/asio/windows/basic_stream_handle.hpp>
+#include <boost/asio/windows/object_handle.hpp>
+#include <boost/asio/windows/object_handle_service.hpp>
 #include <boost/asio/windows/overlapped_ptr.hpp>
 #include <boost/asio/windows/random_access_handle.hpp>
 #include <boost/asio/windows/random_access_handle_service.hpp>
Modified: trunk/boost/asio/detail/config.hpp
==============================================================================
--- trunk/boost/asio/detail/config.hpp	(original)
+++ trunk/boost/asio/detail/config.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -311,6 +311,13 @@
 # endif // defined(BOOST_ASIO_HAS_IOCP)
 #endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
 
+// Windows: object handles.
+#if !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE)
+# if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#  define BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE 1
+# endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE)
+
 // Windows: OVERLAPPED wrapper.
 #if !defined(BOOST_ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
 # if defined(BOOST_ASIO_HAS_IOCP)
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	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -24,10 +24,10 @@
 #include <boost/asio/detail/noncopyable.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue.hpp>
 #include <boost/asio/detail/timer_scheduler.hpp>
 #include <boost/asio/detail/wait_handler.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
 
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	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -31,10 +31,10 @@
 #include <boost/asio/detail/reactor_op_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 #include <boost/asio/detail/timer_queue_fwd.hpp>
 #include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 #include <boost/asio/io_service.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
@@ -125,7 +125,7 @@
   template <typename Time_Traits>
   void schedule_timer(timer_queue<Time_Traits>& queue,
       const typename Time_Traits::time_type& time,
-      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp	(original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -29,10 +29,10 @@
 #include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 #include <boost/asio/detail/timer_queue_fwd.hpp>
 #include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
 
@@ -147,7 +147,7 @@
   template <typename Time_Traits>
   void schedule_timer(timer_queue<Time_Traits>& queue,
       const typename Time_Traits::time_type& time,
-      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.hpp	(original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -40,7 +40,7 @@
 template <typename Time_Traits>
 void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
     const typename Time_Traits::time_type& time,
-    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
 {
   boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
Modified: trunk/boost/asio/detail/impl/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.hpp	(original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -38,7 +38,7 @@
 template <typename Time_Traits>
 void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
     const typename Time_Traits::time_type& time,
-    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
 {
   mutex::scoped_lock lock(mutex_);
 
Modified: trunk/boost/asio/detail/impl/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.hpp	(original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -42,7 +42,7 @@
 template <typename Time_Traits>
 void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
     const typename Time_Traits::time_type& time,
-    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
 {
   boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
Modified: trunk/boost/asio/detail/impl/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.hpp	(original)
+++ trunk/boost/asio/detail/impl/select_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -44,7 +44,7 @@
 template <typename Time_Traits>
 void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
     const typename Time_Traits::time_type& time,
-    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
 {
   boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
Modified: trunk/boost/asio/detail/impl/timer_queue_ptime.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/timer_queue_ptime.ipp	(original)
+++ trunk/boost/asio/detail/impl/timer_queue_ptime.ipp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -33,7 +33,7 @@
 }
 
 bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
-    const time_type& time, per_timer_data& timer, timer_op* op)
+    const time_type& time, per_timer_data& timer, wait_op* op)
 {
   return impl_.enqueue_timer(time, timer, op);
 }
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	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -87,7 +87,7 @@
 template <typename Time_Traits>
 void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
     const typename Time_Traits::time_type& time,
-    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
 {
   // If the service has been shut down we silently discard the timer.
   if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
Added: trunk/boost/asio/detail/impl/win_object_handle_service.ipp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/impl/win_object_handle_service.ipp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,446 @@
+//
+// detail/impl/win_object_handle_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2011 Boris Schaeling (boris_at_[hidden])
+//
+// 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_OBJECT_HANDLE_SERVICE_IPP
+#define BOOST_ASIO_DETAIL_IMPL_WIN_OBJECT_HANDLE_SERVICE_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_HAS_WINDOWS_OBJECT_HANDLE)
+
+#include <boost/asio/detail/win_object_handle_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+win_object_handle_service::win_object_handle_service(
+    boost::asio::io_service& io_service)
+  : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
+    mutex_(),
+    impl_list_(0),
+    shutdown_(false)
+{
+}
+
+void win_object_handle_service::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+
+  // Setting this flag to true prevents new objects from being registered, and
+  // new asynchronous wait operations from being started. We only need to worry
+  // about cleaning up the operations that are currently in progress.
+  shutdown_ = true;
+
+  op_queue<operation> ops;
+  for (implementation_type* impl = impl_list_; impl; impl = impl->next_)
+    ops.push(impl->op_queue_);
+
+  lock.unlock();
+
+  io_service_.abandon_operations(ops);
+}
+
+void win_object_handle_service::construct(
+    win_object_handle_service::implementation_type& impl)
+{
+  impl.handle_ = INVALID_HANDLE_VALUE;
+  impl.wait_handle_ = INVALID_HANDLE_VALUE;
+  impl.owner_ = this;
+
+  // Insert implementation into linked list of all implementations.
+  mutex::scoped_lock lock(mutex_);
+  if (!shutdown_)
+  {
+    impl.next_ = impl_list_;
+    impl.prev_ = 0;
+    if (impl_list_)
+      impl_list_->prev_ = &impl;
+    impl_list_ = &impl;
+  }
+}
+
+void win_object_handle_service::move_construct(
+    win_object_handle_service::implementation_type& impl,
+    win_object_handle_service::implementation_type& other_impl)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  // Insert implementation into linked list of all implementations.
+  if (!shutdown_)
+  {
+    impl.next_ = impl_list_;
+    impl.prev_ = 0;
+    if (impl_list_)
+      impl_list_->prev_ = &impl;
+    impl_list_ = &impl;
+  }
+
+  impl.handle_ = other_impl.handle_;
+  other_impl.handle_ = INVALID_HANDLE_VALUE;
+  impl.wait_handle_ = other_impl.wait_handle_;
+  other_impl.wait_handle_ = INVALID_HANDLE_VALUE;
+  impl.op_queue_.push(other_impl.op_queue_);
+  impl.owner_ = this;
+
+  // We must not hold the lock while calling UnregisterWaitEx. This is because
+  // the registered callback function might be invoked while we are waiting for
+  // UnregisterWaitEx to complete.
+  lock.unlock();
+
+  if (impl.wait_handle_ != INVALID_HANDLE_VALUE)
+    ::UnregisterWaitEx(impl.wait_handle_, INVALID_HANDLE_VALUE);
+
+  if (!impl.op_queue_.empty())
+    register_wait_callback(impl, lock);
+}
+
+void win_object_handle_service::move_assign(
+    win_object_handle_service::implementation_type& impl,
+    win_object_handle_service& other_service,
+    win_object_handle_service::implementation_type& other_impl)
+{
+  boost::system::error_code ignored_ec;
+  close(impl, ignored_ec);
+
+  mutex::scoped_lock lock(mutex_);
+
+  if (this != &other_service)
+  {
+    // Remove implementation from linked list of all implementations.
+    if (impl_list_ == &impl)
+      impl_list_ = impl.next_;
+    if (impl.prev_)
+      impl.prev_->next_ = impl.next_;
+    if (impl.next_)
+      impl.next_->prev_= impl.prev_;
+    impl.next_ = 0;
+    impl.prev_ = 0;
+  }
+
+  impl.handle_ = other_impl.handle_;
+  other_impl.handle_ = INVALID_HANDLE_VALUE;
+  impl.wait_handle_ = other_impl.wait_handle_;
+  other_impl.wait_handle_ = INVALID_HANDLE_VALUE;
+  impl.op_queue_.push(other_impl.op_queue_);
+  impl.owner_ = this;
+
+  if (this != &other_service)
+  {
+    // Insert implementation into linked list of all implementations.
+    impl.next_ = other_service.impl_list_;
+    impl.prev_ = 0;
+    if (other_service.impl_list_)
+      other_service.impl_list_->prev_ = &impl;
+    other_service.impl_list_ = &impl;
+  }
+
+  // We must not hold the lock while calling UnregisterWaitEx. This is because
+  // the registered callback function might be invoked while we are waiting for
+  // UnregisterWaitEx to complete.
+  lock.unlock();
+
+  if (impl.wait_handle_ != INVALID_HANDLE_VALUE)
+    ::UnregisterWaitEx(impl.wait_handle_, INVALID_HANDLE_VALUE);
+
+  if (!impl.op_queue_.empty())
+    register_wait_callback(impl, lock);
+}
+
+void win_object_handle_service::destroy(
+    win_object_handle_service::implementation_type& impl)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  // Remove implementation from linked list of all implementations.
+  if (impl_list_ == &impl)
+    impl_list_ = impl.next_;
+  if (impl.prev_)
+    impl.prev_->next_ = impl.next_;
+  if (impl.next_)
+    impl.next_->prev_= impl.prev_;
+  impl.next_ = 0;
+  impl.prev_ = 0;
+
+  if (is_open(impl))
+  {
+    BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "close"));
+
+    HANDLE wait_handle = impl.wait_handle_;
+    impl.wait_handle_ = INVALID_HANDLE_VALUE;
+
+    op_queue<operation> ops;
+    while (wait_op* op = impl.op_queue_.front())
+    {
+      op->ec_ = boost::asio::error::operation_aborted;
+      impl.op_queue_.pop();
+      ops.push(op);
+    }
+
+    // We must not hold the lock while calling UnregisterWaitEx. This is
+    // because the registered callback function might be invoked while we are
+    // waiting for UnregisterWaitEx to complete.
+    lock.unlock();
+
+    if (wait_handle != INVALID_HANDLE_VALUE)
+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);
+
+    ::CloseHandle(impl.handle_);
+    impl.handle_ = INVALID_HANDLE_VALUE;
+
+    io_service_.post_deferred_completions(ops);
+  }
+}
+
+boost::system::error_code win_object_handle_service::assign(
+    win_object_handle_service::implementation_type& impl,
+    const native_handle_type& handle, boost::system::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = boost::asio::error::already_open;
+    return ec;
+  }
+
+  impl.handle_ = handle;
+  ec = boost::system::error_code();
+  return ec;
+}
+
+boost::system::error_code win_object_handle_service::close(
+    win_object_handle_service::implementation_type& impl,
+    boost::system::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "close"));
+
+    mutex::scoped_lock lock(mutex_);
+
+    HANDLE wait_handle = impl.wait_handle_;
+    impl.wait_handle_ = INVALID_HANDLE_VALUE;
+
+    op_queue<operation> completed_ops;
+    while (wait_op* op = impl.op_queue_.front())
+    {
+      impl.op_queue_.pop();
+      op->ec_ = boost::asio::error::operation_aborted;
+      completed_ops.push(op);
+    }
+
+    // We must not hold the lock while calling UnregisterWaitEx. This is
+    // because the registered callback function might be invoked while we are
+    // waiting for UnregisterWaitEx to complete.
+    lock.unlock();
+
+    if (wait_handle != INVALID_HANDLE_VALUE)
+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);
+
+    if (::CloseHandle(impl.handle_))
+    {
+      impl.handle_ = INVALID_HANDLE_VALUE;
+      ec = boost::system::error_code();
+    }
+    else
+    {
+      DWORD last_error = ::GetLastError();
+      ec = boost::system::error_code(last_error,
+          boost::asio::error::get_system_category());
+    }
+
+    io_service_.post_deferred_completions(completed_ops);
+  }
+  else
+  {
+    ec = boost::system::error_code();
+  }
+
+  return ec;
+}
+
+boost::system::error_code win_object_handle_service::cancel(
+    win_object_handle_service::implementation_type& impl,
+    boost::system::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "cancel"));
+
+    mutex::scoped_lock lock(mutex_);
+
+    HANDLE wait_handle = impl.wait_handle_;
+    impl.wait_handle_ = INVALID_HANDLE_VALUE;
+
+    op_queue<operation> completed_ops;
+    while (wait_op* op = impl.op_queue_.front())
+    {
+      op->ec_ = boost::asio::error::operation_aborted;
+      impl.op_queue_.pop();
+      completed_ops.push(op);
+    }
+
+    // We must not hold the lock while calling UnregisterWaitEx. This is
+    // because the registered callback function might be invoked while we are
+    // waiting for UnregisterWaitEx to complete.
+    lock.unlock();
+
+    if (wait_handle != INVALID_HANDLE_VALUE)
+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);
+
+    ec = boost::system::error_code();
+
+    io_service_.post_deferred_completions(completed_ops);
+  }
+  else
+  {
+    ec = boost::asio::error::bad_descriptor;
+  }
+
+  return ec;
+}
+
+void win_object_handle_service::wait(
+    win_object_handle_service::implementation_type& impl,
+    boost::system::error_code& ec)
+{
+  switch (::WaitForSingleObject(impl.handle_, INFINITE))
+  {
+  case WAIT_FAILED:
+    {
+      DWORD last_error = ::GetLastError();
+      ec = boost::system::error_code(last_error,
+          boost::asio::error::get_system_category());
+      break;
+    }
+  case WAIT_OBJECT_0:
+  case WAIT_ABANDONED:
+  default:
+    ec = boost::system::error_code();
+    break;
+  }
+}
+
+void win_object_handle_service::start_wait_op(
+    win_object_handle_service::implementation_type& impl, wait_op* op)
+{
+  io_service_.work_started();
+
+  if (is_open(impl))
+  {
+    mutex::scoped_lock lock(mutex_);
+
+    if (!shutdown_)
+    {
+      impl.op_queue_.push(op);
+
+      // Only the first operation to be queued gets to register a wait callback.
+      // Subsequent operations have to wait for the first to finish.
+      if (impl.op_queue_.front() == op)
+        register_wait_callback(impl, lock);
+    }
+    else
+    {
+      lock.unlock();
+      io_service_.post_deferred_completion(op);
+    }
+  }
+  else
+  {
+    op->ec_ = boost::asio::error::bad_descriptor;
+    io_service_.post_deferred_completion(op);
+  }
+}
+
+void win_object_handle_service::register_wait_callback(
+    win_object_handle_service::implementation_type& impl,
+    mutex::scoped_lock& lock)
+{
+  lock.lock();
+
+  if (!RegisterWaitForSingleObject(&impl.wait_handle_,
+        impl.handle_, &win_object_handle_service::wait_callback,
+        &impl, INFINITE, WT_EXECUTEONLYONCE))
+  {
+    DWORD last_error = ::GetLastError();
+    boost::system::error_code ec(last_error,
+        boost::asio::error::get_system_category());
+
+    op_queue<operation> completed_ops;
+    while (wait_op* op = impl.op_queue_.front())
+    {
+      op->ec_ = ec;
+      impl.op_queue_.pop();
+      completed_ops.push(op);
+    }
+
+    lock.unlock();
+    io_service_.post_deferred_completions(completed_ops);
+  }
+}
+
+void win_object_handle_service::wait_callback(PVOID param, BOOLEAN)
+{
+  implementation_type* impl = static_cast<implementation_type*>(param);
+  mutex::scoped_lock lock(impl->owner_->mutex_);
+
+  if (impl->wait_handle_ != INVALID_HANDLE_VALUE)
+  {
+    ::UnregisterWaitEx(impl->wait_handle_, NULL);
+    impl->wait_handle_ = INVALID_HANDLE_VALUE;
+  }
+
+  if (wait_op* op = impl->op_queue_.front())
+  {
+    op_queue<operation> completed_ops;
+
+    op->ec_ = boost::system::error_code();
+    impl->op_queue_.pop();
+    completed_ops.push(op);
+
+    if (!impl->op_queue_.empty())
+    {
+      if (!RegisterWaitForSingleObject(&impl->wait_handle_,
+            impl->handle_, &win_object_handle_service::wait_callback,
+            param, INFINITE, WT_EXECUTEONLYONCE))
+      {
+        DWORD last_error = ::GetLastError();
+        boost::system::error_code ec(last_error,
+            boost::asio::error::get_system_category());
+
+        while (wait_op* op = impl->op_queue_.front())
+        {
+          op->ec_ = ec;
+          impl->op_queue_.pop();
+          completed_ops.push(op);
+        }
+      }
+    }
+
+    lock.unlock();
+    impl->owner_->io_service_.post_deferred_completions(completed_ops);
+  }
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_WIN_OBJECT_HANDLE_SERVICE_IPP
Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp	(original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -32,10 +32,10 @@
 #include <boost/asio/detail/reactor_op.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 #include <boost/asio/detail/timer_queue_fwd.hpp>
 #include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 #include <boost/asio/error.hpp>
 #include <boost/asio/io_service.hpp>
 
@@ -149,7 +149,7 @@
   template <typename Time_Traits>
   void schedule_timer(timer_queue<Time_Traits>& queue,
       const typename Time_Traits::time_type& time,
-      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp	(original)
+++ trunk/boost/asio/detail/select_reactor.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -32,10 +32,10 @@
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/select_reactor_fwd.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 #include <boost/asio/detail/timer_queue_fwd.hpp>
 #include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 #include <boost/asio/io_service.hpp>
 
 #if defined(BOOST_ASIO_HAS_IOCP)
@@ -134,7 +134,7 @@
   template <typename Time_Traits>
   void schedule_timer(timer_queue<Time_Traits>& queue,
       const typename Time_Traits::time_type& time,
-      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
Deleted: trunk/boost/asio/detail/timer_op.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_op.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
+++ (empty file)
@@ -1,47 +0,0 @@
-//
-// detail/timer_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_TIMER_OP_HPP
-#define BOOST_ASIO_DETAIL_TIMER_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 timer_op
-  : public operation
-{
-public:
-  // The error code to be passed to the completion handler.
-  boost::system::error_code ec_;
-
-protected:
-  timer_op(func_type func)
-    : operation(func)
-  {
-  }
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_TIMER_OP_HPP
Modified: trunk/boost/asio/detail/timer_queue.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_queue.hpp	(original)
+++ trunk/boost/asio/detail/timer_queue.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -23,8 +23,8 @@
 #include <boost/cstdint.hpp>
 #include <boost/asio/detail/date_time_fwd.hpp>
 #include <boost/asio/detail/op_queue.hpp>
-#include <boost/asio/detail/timer_op.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 #include <boost/asio/error.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
@@ -54,7 +54,7 @@
     friend class timer_queue;
 
     // The operations waiting on the timer.
-    op_queue<timer_op> op_queue_;
+    op_queue<wait_op> op_queue_;
 
     // The index of the timer in the heap.
     std::size_t heap_index_;
@@ -74,7 +74,7 @@
   // Add a new timer to the queue. Returns true if this is the timer that is
   // earliest in the queue, in which case the reactor's event demultiplexing
   // function call may need to be interrupted and restarted.
-  bool enqueue_timer(const time_type& time, per_timer_data& timer, timer_op* op)
+  bool enqueue_timer(const time_type& time, per_timer_data& timer, wait_op* op)
   {
     // Enqueue the timer object.
     if (timer.prev_ == 0 && &timer != timers_)
@@ -176,7 +176,7 @@
     std::size_t num_cancelled = 0;
     if (timer.prev_ != 0 || &timer == timers_)
     {
-      while (timer_op* op = (num_cancelled != max_cancelled)
+      while (wait_op* op = (num_cancelled != max_cancelled)
           ? timer.op_queue_.front() : 0)
       {
         op->ec_ = boost::asio::error::operation_aborted;
Modified: trunk/boost/asio/detail/timer_queue_ptime.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_queue_ptime.hpp	(original)
+++ trunk/boost/asio/detail/timer_queue_ptime.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -52,7 +52,7 @@
   // earliest in the queue, in which case the reactor's event demultiplexing
   // function call may need to be interrupted and restarted.
   BOOST_ASIO_DECL bool enqueue_timer(const time_type& time,
-      per_timer_data& timer, timer_op* op);
+      per_timer_data& timer, wait_op* op);
 
   // Whether there are no timers in the queue.
   BOOST_ASIO_DECL virtual bool empty() const;
Modified: trunk/boost/asio/detail/wait_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/wait_handler.hpp	(original)
+++ trunk/boost/asio/detail/wait_handler.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -19,7 +19,8 @@
 #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/timer_op.hpp>
+#include <boost/asio/detail/wait_op.hpp>
+#include <boost/asio/io_service.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
 
@@ -28,13 +29,13 @@
 namespace detail {
 
 template <typename Handler>
-class wait_handler : public timer_op
+class wait_handler : public wait_op
 {
 public:
   BOOST_ASIO_DEFINE_HANDLER_PTR(wait_handler);
 
   wait_handler(Handler& h)
-    : timer_op(&wait_handler::do_complete),
+    : wait_op(&wait_handler::do_complete),
       handler_(BOOST_ASIO_MOVE_CAST(Handler)(h))
   {
   }
Added: trunk/boost/asio/detail/wait_op.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/wait_op.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,47 @@
+//
+// detail/wait_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_WAIT_OP_HPP
+#define BOOST_ASIO_DETAIL_WAIT_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 wait_op
+  : public operation
+{
+public:
+  // The error code to be passed to the completion handler.
+  boost::system::error_code ec_;
+
+protected:
+  wait_op(func_type func)
+    : operation(func)
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WAIT_OP_HPP
Modified: trunk/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_io_service.hpp	(original)
+++ trunk/boost/asio/detail/win_iocp_io_service.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -26,13 +26,13 @@
 #include <boost/asio/detail/op_queue.hpp>
 #include <boost/asio/detail/scoped_ptr.hpp>
 #include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/timer_op.hpp>
+#include <boost/asio/detail/thread.hpp>
 #include <boost/asio/detail/timer_queue_base.hpp>
 #include <boost/asio/detail/timer_queue_fwd.hpp>
 #include <boost/asio/detail/timer_queue_set.hpp>
+#include <boost/asio/detail/wait_op.hpp>
 #include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
 #include <boost/asio/detail/win_iocp_operation.hpp>
-#include <boost/asio/detail/thread.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
 
@@ -40,7 +40,7 @@
 namespace asio {
 namespace detail {
 
-class timer_op;
+class wait_op;
 
 class win_iocp_io_service
   : public boost::asio::detail::service_base<win_iocp_io_service>
@@ -169,7 +169,7 @@
   template <typename Time_Traits>
   void schedule_timer(timer_queue<Time_Traits>& queue,
       const typename Time_Traits::time_type& time,
-      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
 
   // Cancel the timer associated with the given token. Returns the number of
   // handlers that have been posted or dispatched.
Added: trunk/boost/asio/detail/win_object_handle_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/win_object_handle_service.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,185 @@
+//
+// detail/win_object_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2011 Boris Schaeling (boris_at_[hidden])
+//
+// 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_OBJECT_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_OBJECT_HANDLE_SERVICE_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_HAS_WINDOWS_OBJECT_HANDLE)
+
+#include <boost/utility/addressof.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/wait_handler.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_object_handle_service
+{
+public:
+  // The native type of an object handle.
+  typedef HANDLE native_handle_type;
+
+  // The implementation type of the object handle.
+  class implementation_type
+  {
+   public:
+    // Default constructor.
+    implementation_type()
+      : handle_(INVALID_HANDLE_VALUE),
+        wait_handle_(INVALID_HANDLE_VALUE),
+        owner_(0),
+        next_(0),
+        prev_(0)
+    {
+    }
+
+  private:
+    // Only this service will have access to the internal values.
+    friend class win_object_handle_service;
+
+    // The native object handle representation. May be accessed or modified
+    // without locking the mutex.
+    native_handle_type handle_;
+
+    // The handle used to unregister the wait operation. The mutex must be
+    // locked when accessing or modifying this member.
+    HANDLE wait_handle_;
+
+    // The operations waiting on the object handle. If there is a registered
+    // wait then the mutex must be locked when accessing or modifying this
+    // member
+    op_queue<wait_op> op_queue_;
+
+    // The service instance that owns the object handle implementation.
+    win_object_handle_service* owner_;
+
+    // Pointers to adjacent handle implementations in linked list. The mutex
+    // must be locked when accessing or modifying these members.
+    implementation_type* next_;
+    implementation_type* prev_;
+  };
+
+  // Constructor.
+  BOOST_ASIO_DECL win_object_handle_service(
+      boost::asio::io_service& io_service);
+
+  // Destroy all user-defined handler objects owned by the service.
+  BOOST_ASIO_DECL void shutdown_service();
+
+  // Construct a new handle implementation.
+  BOOST_ASIO_DECL void construct(implementation_type& impl);
+
+  // Move-construct a new handle implementation.
+  BOOST_ASIO_DECL void move_construct(implementation_type& impl,
+      implementation_type& other_impl);
+
+  // Move-assign from another handle implementation.
+  BOOST_ASIO_DECL void move_assign(implementation_type& impl,
+      win_object_handle_service& other_service,
+      implementation_type& other_impl);
+
+  // Destroy a handle implementation.
+  BOOST_ASIO_DECL void destroy(implementation_type& impl);
+
+  // Assign a native handle to a handle implementation.
+  BOOST_ASIO_DECL boost::system::error_code assign(implementation_type& impl,
+      const native_handle_type& handle, boost::system::error_code& ec);
+
+  // Determine whether the handle is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return impl.handle_ != INVALID_HANDLE_VALUE && impl.handle_ != 0;
+  }
+
+  // Destroy a handle implementation.
+  BOOST_ASIO_DECL boost::system::error_code close(implementation_type& impl,
+      boost::system::error_code& ec);
+
+  // Get the native handle representation.
+  native_handle_type native_handle(const implementation_type& impl) const
+  {
+    return impl.handle_;
+  }
+
+  // Cancel all operations associated with the handle.
+  BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl,
+      boost::system::error_code& ec);
+
+  // Perform a synchronous wait for the object to enter a signalled state.
+  BOOST_ASIO_DECL void wait(implementation_type& impl,
+      boost::system::error_code& ec);
+
+  /// Start an asynchronous wait.
+  template <typename Handler>
+  void async_wait(implementation_type& impl, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef wait_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, "object_handle", &impl, "async_wait"));
+
+    start_wait_op(impl, p.p);
+    p.v = p.p = 0;
+  }
+
+private:
+  // Helper function to start an asynchronous wait operation.
+  BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, wait_op* op);
+
+  // Helper function to register a wait operation.
+  BOOST_ASIO_DECL void register_wait_callback(
+      implementation_type& impl, mutex::scoped_lock& lock);
+
+  // Callback function invoked when the registered wait completes.
+  static BOOST_ASIO_DECL VOID CALLBACK wait_callback(
+      PVOID param, BOOLEAN timeout);
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_;
+
+  // Mutex to protect access to internal state.
+  mutex mutex_;
+
+  // The head of a linked list of all implementations.
+  implementation_type* impl_list_;
+
+  // Flag to indicate that the dispatcher has been shut down.
+  bool shutdown_;
+};
+
+} // 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_object_handle_service.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+
+#endif // BOOST_ASIO_DETAIL_WIN_OBJECT_HANDLE_SERVICE_HPP
Modified: trunk/boost/asio/impl/src.hpp
==============================================================================
--- trunk/boost/asio/impl/src.hpp	(original)
+++ trunk/boost/asio/impl/src.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -53,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_object_handle_service.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>
Added: trunk/boost/asio/windows/basic_object_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/basic_object_handle.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,177 @@
+//
+// windows/basic_object_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2011 Boris Schaeling (boris_at_[hidden])
+//
+// 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_WINDOWS_BASIC_OBJECT_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_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_HAS_WINDOWS_OBJECT_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/object_handle_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides object-oriented handle functionality.
+/**
+ * The windows::basic_object_handle class template provides asynchronous and
+ * blocking object-oriented handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename ObjectHandleService = object_handle_service>
+class basic_object_handle
+  : public basic_handle<ObjectHandleService>
+{
+public:
+  /// The native representation of a handle.
+  typedef typename ObjectHandleService::native_handle_type native_handle_type;
+
+  /// Construct a basic_object_handle without opening it.
+  /**
+   * This constructor creates an object handle without opening it.
+   *
+   * @param io_service The io_service object that the object handle will use to
+   * dispatch handlers for any asynchronous operations performed on the handle.
+   */
+  explicit basic_object_handle(boost::asio::io_service& io_service)
+    : basic_handle<ObjectHandleService>(io_service)
+  {
+  }
+
+  /// Construct a basic_object_handle on an existing native handle.
+  /**
+   * This constructor creates an object handle object to hold an existing native
+   * handle.
+   *
+   * @param io_service The io_service object that the object handle will use to
+   * dispatch handlers for any asynchronous operations performed on the handle.
+   *
+   * @param native_handle The new underlying handle implementation.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  basic_object_handle(boost::asio::io_service& io_service,
+      const native_handle_type& native_handle)
+    : basic_handle<ObjectHandleService>(io_service, native_handle)
+  {
+  }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Move-construct a basic_object_handle from another.
+  /**
+   * This constructor moves an object handle from one object to another.
+   *
+   * @param other The other basic_object_handle object from which the move will
+   * occur.
+   *
+   * @note Following the move, the moved-from object is in the same state as if
+   * constructed using the @c basic_object_handle(io_service&) constructor.
+   */
+  basic_object_handle(basic_object_handle&& other)
+    : basic_handle<ObjectHandleService>(
+        BOOST_ASIO_MOVE_CAST(basic_object_handle)(other))
+  {
+  }
+
+  /// Move-assign a basic_object_handle from another.
+  /**
+   * This assignment operator moves an object handle from one object to another.
+   *
+   * @param other The other basic_object_handle object from which the move will
+   * occur.
+   *
+   * @note Following the move, the moved-from object is in the same state as if
+   * constructed using the @c basic_object_handle(io_service&) constructor.
+   */
+  basic_object_handle& operator=(basic_object_handle&& other)
+  {
+    basic_handle<ObjectHandleService>::operator=(
+        BOOST_ASIO_MOVE_CAST(basic_object_handle)(other));
+    return *this;
+  }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+  /// Perform a blocking wait on the object handle.
+  /**
+   * This function is used to wait for the object handle to be set to the
+   * signalled state. This function blocks and does not return until the object
+   * handle has been set to the signalled state.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  void wait()
+  {
+    boost::system::error_code ec;
+    this->service.wait(this->implementation, ec);
+    boost::asio::detail::throw_error(ec, "wait");
+  }
+
+  /// Perform a blocking wait on the object handle.
+  /**
+   * This function is used to wait for the object handle to be set to the
+   * signalled state. This function blocks and does not return until the object
+   * handle has been set to the signalled state.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  void wait(boost::system::error_code& ec)
+  {
+    this->service.wait(this->implementation, ec);
+  }
+
+  /// Start an asynchronous wait on the object handle.
+  /**
+   * This function is be used to initiate an asynchronous wait against the
+   * object handle. It always returns immediately.
+   *
+   * @param handler The handler to be called when the object handle is set to
+   * the signalled state. 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.
+   * ); @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 WaitHandler>
+  void async_wait(WaitHandler handler)
+  {
+    this->service.async_wait(this->implementation, handler);
+  }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
Added: trunk/boost/asio/windows/object_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/object_handle.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,40 @@
+//
+// windows/object_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2011 Boris Schaeling (boris_at_[hidden])
+//
+// 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_WINDOWS_OBJECT_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_OBJECT_HANDLE_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_HAS_WINDOWS_OBJECT_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/windows/basic_object_handle.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Typedef for the typical usage of an object handle.
+typedef basic_object_handle<> object_handle;
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_WINDOWS_OBJECT_HANDLE_HPP
Added: trunk/boost/asio/windows/object_handle_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/object_handle_service.hpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,170 @@
+//
+// windows/object_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2011 Boris Schaeling (boris_at_[hidden])
+//
+// 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_WINDOWS_OBJECT_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_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_HAS_WINDOWS_OBJECT_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/win_object_handle_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Default service implementation for an object handle.
+class object_handle_service
+#if defined(GENERATING_DOCUMENTATION)
+  : public boost::asio::io_service::service
+#else
+  : public boost::asio::detail::service_base<object_handle_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+  /// The unique service identifier.
+  static boost::asio::io_service::id id;
+#endif
+
+private:
+  // The type of the platform-specific implementation.
+  typedef detail::win_object_handle_service service_impl_type;
+
+public:
+  /// The type of an object handle implementation.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined implementation_type;
+#else
+  typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+  /// The native handle type.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined native_handle_type;
+#else
+  typedef service_impl_type::native_handle_type native_handle_type;
+#endif
+
+  /// Construct a new object handle service for the specified io_service.
+  explicit object_handle_service(boost::asio::io_service& io_service)
+    : boost::asio::detail::service_base<object_handle_service>(io_service),
+      service_impl_(io_service)
+  {
+  }
+
+  /// Construct a new object handle implementation.
+  void construct(implementation_type& impl)
+  {
+    service_impl_.construct(impl);
+  }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Move-construct a new object handle implementation.
+  void move_construct(implementation_type& impl,
+      implementation_type& other_impl)
+  {
+    service_impl_.move_construct(impl, other_impl);
+  }
+
+  /// Move-assign from another object handle implementation.
+  void move_assign(implementation_type& impl,
+      object_handle_service& other_service,
+      implementation_type& other_impl)
+  {
+    service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+  }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+  /// Destroy an object handle implementation.
+  void destroy(implementation_type& impl)
+  {
+    service_impl_.destroy(impl);
+  }
+
+  /// Assign an existing native handle to an object handle.
+  boost::system::error_code assign(implementation_type& impl,
+      const native_handle_type& handle, boost::system::error_code& ec)
+  {
+    return service_impl_.assign(impl, handle, ec);
+  }
+
+  /// Determine whether the handle is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return service_impl_.is_open(impl);
+  }
+
+  /// Close an object handle implementation.
+  boost::system::error_code close(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    return service_impl_.close(impl, ec);
+  }
+
+  /// Get the native handle implementation.
+  native_handle_type native_handle(implementation_type& impl)
+  {
+    return service_impl_.native_handle(impl);
+  }
+
+  /// Cancel all asynchronous operations associated with the handle.
+  boost::system::error_code cancel(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    return service_impl_.cancel(impl, ec);
+  }
+
+  // Wait for a signaled state.
+  void wait(implementation_type& impl, boost::system::error_code& ec)
+  {
+    service_impl_.wait(impl, ec);
+  }
+
+  /// Start an asynchronous wait.
+  template <typename WaitHandler>
+  void async_wait(implementation_type& impl,
+      BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+  {
+    service_impl_.async_wait(impl, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+  }
+
+private:
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    service_impl_.shutdown_service();
+  }
+
+  // The platform-specific implementation.
+  service_impl_type service_impl_;
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_HPP
Modified: trunk/libs/asio/doc/overview/windows.qbk
==============================================================================
--- trunk/libs/asio/doc/overview/windows.qbk	(original)
+++ trunk/libs/asio/doc/overview/windows.qbk	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -11,6 +11,8 @@
 
 [link boost_asio.overview.windows.random_access_handle Random-Access HANDLEs]
 
+[link boost_asio.overview.windows.object_handle Object HANDLEs]
+
 [section:stream_handle Stream-Oriented HANDLEs]
 
 Boost.Asio contains classes to allow asynchronous read and write operations to be
@@ -88,4 +90,43 @@
 
 [endsect]
 
+[/-----------------------------------------------------------------------------]
+
+[section:object_handle Object HANDLEs]
+
+Boost.Asio provides Windows-specific classes that permit asynchronous wait operations
+to be performed on HANDLEs to kernel objects of the following types:
+
+  * Change notification
+  * Console input
+  * Event
+  * Memory resource notification
+  * Process
+  * Semaphore
+  * Thread
+  * Waitable timer
+
+For example, to perform asynchronous operations on an event, the following
+object may be created:
+
+  HANDLE handle = ::CreateEvent(...);
+  windows::object_handle file(my_io_service, handle);
+
+The `wait()` and `async_wait()` member functions may then be used to wait until
+the kernel object is signalled.
+
+[heading See Also]
+
+[link boost_asio.reference.windows__object_handle windows::object_handle],
+[link boost_asio.reference.windows__basic_object_handle windows::basic_object_handle],
+[link boost_asio.reference.windows__object_handle_service windows::object_handle_service].
+
+[heading Notes]
+
+Windows object `HANDLE`s are only available at compile time when targeting
+Windows. Programs may test for the macro `BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE` to
+determine whether they are supported.
+
+[endsect]
+
 [endsect]
Modified: trunk/libs/asio/test/Jamfile.v2
==============================================================================
--- trunk/libs/asio/test/Jamfile.v2	(original)
+++ trunk/libs/asio/test/Jamfile.v2	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -197,10 +197,16 @@
   [ link waitable_timer_service.cpp : $(USE_SELECT) : waitable_timer_service_select ]
   [ link windows/basic_handle.cpp : : windows_basic_handle ]
   [ link windows/basic_handle.cpp : $(USE_SELECT) : windows_basic_handle_select ]
+  [ link windows/basic_object_handle.cpp : : windows_basic_object_handle ]
+  [ link windows/basic_object_handle.cpp : $(USE_SELECT) : windows_basic_object_handle_select ]
   [ link windows/basic_random_access_handle.cpp : : windows_basic_random_access_handle ]
   [ link windows/basic_random_access_handle.cpp : $(USE_SELECT) : windows_basic_random_access_handle_select ]
   [ link windows/basic_stream_handle.cpp : : windows_basic_stream_handle ]
   [ link windows/basic_stream_handle.cpp : $(USE_SELECT) : windows_basic_stream_handle_select ]
+  [ link windows/object_handle.cpp : : windows_object_handle ]
+  [ link windows/object_handle.cpp : $(USE_SELECT) : windows_object_handle_select ]
+  [ link windows/object_handle_service.cpp : : windows_object_handle_service ]
+  [ link windows/object_handle_service.cpp : $(USE_SELECT) : windows_object_handle_service_select ]
   [ link windows/overlapped_ptr.cpp : : windows_overlapped_ptr ]
   [ link windows/overlapped_ptr.cpp : $(USE_SELECT) : windows_overlapped_ptr_select ]
   [ link windows/random_access_handle.cpp : : windows_random_access_handle ]
Added: trunk/libs/asio/test/windows/basic_object_handle.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/basic_object_handle.cpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,27 @@
+//
+// basic_object_handle.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/windows/basic_object_handle.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/basic_object_handle");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/windows/object_handle.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/object_handle.cpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,117 @@
+//
+// object_handle.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/windows/object_handle.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_object_handle_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::object_handle compile and link correctly. Runtime failures are
+// ignored.
+
+namespace windows_object_handle_compile {
+
+void wait_handler(const boost::system::error_code&)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+  using namespace boost::asio;
+  namespace win = boost::asio::windows;
+
+  try
+  {
+    io_service ios;
+    boost::system::error_code ec;
+
+    // basic_object_handle constructors.
+
+    win::object_handle handle1(ios);
+    HANDLE native_handle1 = INVALID_HANDLE_VALUE;
+    win::object_handle handle2(ios, native_handle1);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+    win::object_handle handle3(std::move(handle2));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+    // basic_object_handle operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+    handle1 = win::object_handle(ios);
+    handle1 = std::move(handle2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+    // basic_io_object functions.
+
+    io_service& ios_ref = handle1.get_io_service();
+    (void)ios_ref;
+
+    // basic_handle functions.
+
+    win::object_handle::lowest_layer_type& lowest_layer
+      = handle1.lowest_layer();
+    (void)lowest_layer;
+
+    const win::object_handle& handle4 = handle1;
+    const win::object_handle::lowest_layer_type& lowest_layer2
+      = handle4.lowest_layer();
+    (void)lowest_layer2;
+
+    HANDLE native_handle2 = INVALID_HANDLE_VALUE;
+    handle1.assign(native_handle2);
+
+    bool is_open = handle1.is_open();
+    (void)is_open;
+
+    handle1.close();
+    handle1.close(ec);
+
+    win::object_handle::native_handle_type native_handle3
+      = handle1.native_handle();
+    (void)native_handle3;
+
+    handle1.cancel();
+    handle1.cancel(ec);
+
+    // basic_object_handle functions.
+
+    handle1.wait();
+    handle1.wait(ec);
+
+    handle1.async_wait(&wait_handler);
+  }
+  catch (std::exception&)
+  {
+  }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+}
+
+} // namespace windows_object_handle_compile
+
+//------------------------------------------------------------------------------
+test_suite* init_unit_test_suite(int, char*[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/object_handle");
+  test->add(BOOST_TEST_CASE(&windows_object_handle_compile::test));
+  return test;
+}
Added: trunk/libs/asio/test/windows/object_handle_service.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/object_handle_service.cpp	2012-01-10 04:58:05 EST (Tue, 10 Jan 2012)
@@ -0,0 +1,27 @@
+//
+// object_handle_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/windows/object_handle_service.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+test_suite* init_unit_test_suite(int, char*[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/object_handle_service");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}