$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: chris_at_[hidden]
Date: 2008-04-21 01:32:35
Author: chris_kohlhoff
Date: 2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
New Revision: 44676
URL: http://svn.boost.org/trac/boost/changeset/44676
Log:
Add new wrapper classes for stream-oriented handles on Windows.
Added:
   trunk/boost/asio/detail/win_iocp_handle_service.hpp   (contents, props changed)
   trunk/boost/asio/windows/
   trunk/boost/asio/windows/basic_handle.hpp   (contents, props changed)
   trunk/boost/asio/windows/basic_stream_handle.hpp   (contents, props changed)
   trunk/boost/asio/windows/stream_handle.hpp   (contents, props changed)
   trunk/boost/asio/windows/stream_handle_service.hpp   (contents, props changed)
   trunk/libs/asio/test/windows/
   trunk/libs/asio/test/windows/basic_handle.cpp   (contents, props changed)
   trunk/libs/asio/test/windows/basic_stream_handle.cpp   (contents, props changed)
   trunk/libs/asio/test/windows/stream_handle.cpp   (contents, props changed)
   trunk/libs/asio/test/windows/stream_handle_service.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/asio.hpp                                |     4 ++++                                    
   trunk/boost/asio/detail/win_iocp_io_service.hpp     |    15 +++++++++++++--                         
   trunk/boost/asio/detail/win_iocp_socket_service.hpp |     6 ++++--                                  
   trunk/libs/asio/test/Jamfile                        |     4 ++++                                    
   trunk/libs/asio/test/Jamfile.v2                     |     8 ++++++++                                
   5 files changed, 33 insertions(+), 4 deletions(-)
Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp	(original)
+++ trunk/boost/asio.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -77,6 +77,10 @@
 #include <boost/asio/streambuf.hpp>
 #include <boost/asio/time_traits.hpp>
 #include <boost/asio/version.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/basic_stream_handle.hpp>
+#include <boost/asio/windows/stream_handle.hpp>
+#include <boost/asio/windows/stream_handle_service.hpp>
 #include <boost/asio/write.hpp>
 
 #endif // BOOST_ASIO_HPP
Added: trunk/boost/asio/detail/win_iocp_handle_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/win_iocp_handle_service.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,756 @@
+//
+// win_iocp_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_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_IOCP_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/win_iocp_io_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_iocp_handle_service
+  : public boost::asio::detail::service_base<win_iocp_handle_service>
+{
+public:
+  // Base class for all operations.
+  typedef win_iocp_io_service::operation operation;
+
+  // The native type of a stream handle.
+  typedef HANDLE native_type;
+
+  // The implementation type of the stream handle.
+  class implementation_type
+  {
+  public:
+    // Default constructor.
+    implementation_type()
+      : handle_(INVALID_HANDLE_VALUE),
+        safe_cancellation_thread_id_(0),
+        next_(0),
+        prev_(0)
+    {
+    }
+
+  private:
+    // Only this service will have access to the internal values.
+    friend class win_iocp_handle_service;
+
+    // The native stream handle representation.
+    native_type handle_;
+
+    // The ID of the thread from which it is safe to cancel asynchronous
+    // operations. 0 means no asynchronous operations have been started yet.
+    // ~0 means asynchronous operations have been started from more than one
+    // thread, and cancellation is not supported for the handle.
+    DWORD safe_cancellation_thread_id_;
+
+    // Pointers to adjacent handle implementations in linked list.
+    implementation_type* next_;
+    implementation_type* prev_;
+  };
+
+  win_iocp_handle_service(boost::asio::io_service& io_service)
+    : boost::asio::detail::service_base<win_iocp_handle_service>(io_service),
+      iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+      mutex_(),
+      impl_list_(0)
+  {
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    // Close all implementations, causing all operations to complete.
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    implementation_type* impl = impl_list_;
+    while (impl)
+    {
+      close_for_destruction(*impl);
+      impl = impl->next_;
+    }
+  }
+
+  // Construct a new handle implementation.
+  void construct(implementation_type& impl)
+  {
+    impl.handle_ = INVALID_HANDLE_VALUE;
+    impl.safe_cancellation_thread_id_ = 0;
+
+    // Insert implementation into linked list of all implementations.
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    impl.next_ = impl_list_;
+    impl.prev_ = 0;
+    if (impl_list_)
+      impl_list_->prev_ = &impl;
+    impl_list_ = &impl;
+  }
+
+  // Destroy a handle implementation.
+  void destroy(implementation_type& impl)
+  {
+    close_for_destruction(impl);
+    
+    // Remove implementation from linked list of all implementations.
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    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;
+  }
+
+  // Assign a native handle to a handle implementation.
+  boost::system::error_code assign(implementation_type& impl,
+      const native_type& native_handle, boost::system::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      ec = boost::asio::error::already_open;
+      return ec;
+    }
+
+    if (iocp_service_.register_handle(native_handle, ec))
+      return ec;
+
+    impl.handle_ = native_handle;
+    ec = boost::system::error_code();
+    return ec;
+  }
+
+  // Determine whether the handle is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return impl.handle_ != INVALID_HANDLE_VALUE;
+  }
+
+  // Destroy a handle implementation.
+  boost::system::error_code close(implementation_type& impl,
+                                  boost::system::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      if (!::CloseHandle(impl.handle_))
+      {
+        DWORD last_error = ::GetLastError();
+        ec = boost::system::error_code(last_error,
+            boost::asio::error::get_system_category());
+        return ec;
+      }
+
+      impl.handle_ = INVALID_HANDLE_VALUE;
+      impl.safe_cancellation_thread_id_ = 0;
+    }
+
+    ec = boost::system::error_code();
+    return ec;
+  }
+
+  // Get the native handle representation.
+  native_type native(implementation_type& impl)
+  {
+    return impl.handle_;
+  }
+
+  // Cancel all operations associated with the handle.
+  boost::system::error_code cancel(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+    }
+    else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+          ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
+    {
+      // The version of Windows supports cancellation from any thread.
+      typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
+      cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+      if (!cancel_io_ex(impl.handle_, 0))
+      {
+        DWORD last_error = ::GetLastError();
+        if (last_error == ERROR_NOT_FOUND)
+        {
+          // ERROR_NOT_FOUND means that there were no operations to be
+          // cancelled. We swallow this error to match the behaviour on other
+          // platforms.
+          ec = boost::system::error_code();
+        }
+        else
+        {
+          ec = boost::system::error_code(last_error,
+              boost::asio::error::get_system_category());
+        }
+      }
+      else
+      {
+        ec = boost::system::error_code();
+      }
+    }
+    else if (impl.safe_cancellation_thread_id_ == 0)
+    {
+      // No operations have been started, so there's nothing to cancel.
+      ec = boost::system::error_code();
+    }
+    else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
+    {
+      // Asynchronous operations have been started from the current thread only,
+      // so it is safe to try to cancel them using CancelIo.
+      if (!::CancelIo(impl.handle_))
+      {
+        DWORD last_error = ::GetLastError();
+        ec = boost::system::error_code(last_error,
+            boost::asio::error::get_system_category());
+      }
+      else
+      {
+        ec = boost::system::error_code();
+      }
+    }
+    else
+    {
+      // Asynchronous operations have been started from more than one thread,
+      // so cancellation is not safe.
+      ec = boost::asio::error::operation_not_supported;
+    }
+
+    return ec;
+  }
+
+  class overlapped_wrapper
+    : public OVERLAPPED
+  {
+  public:
+    explicit overlapped_wrapper(boost::system::error_code& ec)
+    {
+      Internal = 0;
+      InternalHigh = 0;
+      Offset = 0;
+      OffsetHigh = 0;
+
+      // Create a non-signalled manual-reset event, for GetOverlappedResult.
+      hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
+      if (hEvent)
+      {
+        // As documented in GetQueuedCompletionStatus, setting the low order
+        // bit of this event prevents our synchronous writes from being treated
+        // as completion port events.
+        *reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
+      }
+      else
+      {
+        DWORD last_error = ::GetLastError();
+        ec = boost::system::error_code(last_error,
+            boost::asio::error::get_system_category());
+      }
+    }
+
+    ~overlapped_wrapper()
+    {
+      if (hEvent)
+      {
+        ::CloseHandle(hEvent);
+      }
+    }
+  };
+
+  // Write the given data. Returns the number of bytes sent.
+  template <typename ConstBufferSequence>
+  size_t write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return 0;
+    }
+
+    // Find first buffer of non-zero length.
+    boost::asio::const_buffer buffer;
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    for (DWORD i = 0; iter != end; ++iter, ++i)
+    {
+      buffer = boost::asio::const_buffer(*iter);
+      if (boost::asio::buffer_size(buffer) != 0)
+        break;
+    }
+
+    // A request to write 0 bytes on a stream handle is a no-op.
+    if (boost::asio::buffer_size(buffer) == 0)
+    {
+      ec = boost::system::error_code();
+      return 0;
+    }
+
+    overlapped_wrapper overlapped(ec);
+    if (ec)
+    {
+      return 0;
+    }
+
+    // Write the data. 
+    BOOL ok = ::WriteFile(impl.handle_,
+        boost::asio::buffer_cast<LPCVOID>(buffer),
+        static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+    if (!ok) 
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error != ERROR_IO_PENDING)
+      {
+        ec = boost::system::error_code(last_error,
+            boost::asio::error::get_system_category());
+        return 0;
+      }
+    }
+
+    // Wait for the operation to complete.
+    DWORD bytes_transferred = 0;
+    ok = ::GetOverlappedResult(impl.handle_,
+        &overlapped, &bytes_transferred, TRUE);
+    if (!ok)
+    {
+      DWORD last_error = ::GetLastError();
+      ec = boost::system::error_code(last_error,
+          boost::asio::error::get_system_category());
+    }
+
+    ec = boost::system::error_code();
+    return bytes_transferred;
+  }
+
+  template <typename ConstBufferSequence, typename Handler>
+  class write_operation
+    : public operation
+  {
+  public:
+    write_operation(win_iocp_io_service& io_service,
+        const ConstBufferSequence& buffers, Handler handler)
+      : operation(io_service,
+          &write_operation<ConstBufferSequence, Handler>::do_completion_impl,
+          &write_operation<ConstBufferSequence, Handler>::destroy_impl),
+        work_(io_service.get_io_service()),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+  private:
+    static void do_completion_impl(operation* op,
+        DWORD last_error, size_t bytes_transferred)
+    {
+      // Take ownership of the operation object.
+      typedef write_operation<ConstBufferSequence, Handler> op_type;
+      op_type* handler_op(static_cast<op_type*>(op));
+      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+      // Check whether buffers are still valid.
+      typename ConstBufferSequence::const_iterator iter
+        = handler_op->buffers_.begin();
+      typename ConstBufferSequence::const_iterator end
+        = handler_op->buffers_.end();
+      while (iter != end)
+      {
+        boost::asio::const_buffer buffer(*iter);
+        boost::asio::buffer_cast<const char*>(buffer);
+        ++iter;
+      }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+      // Make a copy of the handler so that the memory can be deallocated before
+      // the upcall is made.
+      Handler handler(handler_op->handler_);
+
+      // Free the memory associated with the handler.
+      ptr.reset();
+
+      // Call the handler.
+      boost::system::error_code ec(last_error,
+          boost::asio::error::get_system_category());
+      boost_asio_handler_invoke_helpers::invoke(
+          bind_handler(handler, ec, bytes_transferred), &handler);
+    }
+
+    static void destroy_impl(operation* op)
+    {
+      // Take ownership of the operation object.
+      typedef write_operation<ConstBufferSequence, Handler> op_type;
+      op_type* handler_op(static_cast<op_type*>(op));
+      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+    }
+
+    boost::asio::io_service::work work_;
+    ConstBufferSequence buffers_;
+    Handler handler_;
+  };
+
+  // Start an asynchronous write. The data being written must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, Handler handler)
+  {
+    if (!is_open(impl))
+    {
+      this->get_io_service().post(bind_handler(handler,
+            boost::asio::error::bad_descriptor, 0));
+      return;
+    }
+
+    // Update the ID of the thread from which cancellation is safe.
+    if (impl.safe_cancellation_thread_id_ == 0)
+      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+      impl.safe_cancellation_thread_id_ = ~DWORD(0);
+
+    // Allocate and construct an operation to wrap the handler.
+    typedef write_operation<ConstBufferSequence, Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
+
+    // Find first buffer of non-zero length.
+    boost::asio::const_buffer buffer;
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    for (DWORD i = 0; iter != end; ++iter, ++i)
+    {
+      buffer = boost::asio::const_buffer(*iter);
+      if (boost::asio::buffer_size(buffer) != 0)
+        break;
+    }
+
+    // A request to write 0 bytes on a stream handle is a no-op.
+    if (boost::asio::buffer_size(buffer) == 0)
+    {
+      boost::asio::io_service::work work(this->get_io_service());
+      ptr.reset();
+      boost::system::error_code error;
+      iocp_service_.post(bind_handler(handler, error, 0));
+      return;
+    }
+
+    // Write the data.
+    DWORD bytes_transferred = 0;
+    BOOL ok = ::WriteFile(impl.handle_,
+        boost::asio::buffer_cast<LPCVOID>(buffer),
+        static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+        &bytes_transferred, ptr.get());
+    DWORD last_error = ::GetLastError();
+
+    // Check if the operation completed immediately.
+    if (!ok && last_error != ERROR_IO_PENDING)
+    {
+      boost::asio::io_service::work work(this->get_io_service());
+      ptr.reset();
+      boost::system::error_code ec(last_error,
+          boost::asio::error::get_system_category());
+      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+    }
+    else
+    {
+      ptr.release();
+    }
+  }
+
+  // Read some data. Returns the number of bytes received.
+  template <typename MutableBufferSequence>
+  size_t read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return 0;
+    }
+    
+    // Find first buffer of non-zero length.
+    boost::asio::mutable_buffer buffer;
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    for (DWORD i = 0; iter != end; ++iter, ++i)
+    {
+      buffer = boost::asio::mutable_buffer(*iter);
+      if (boost::asio::buffer_size(buffer) != 0)
+        break;
+    }
+
+    // A request to read 0 bytes on a stream handle is a no-op.
+    if (boost::asio::buffer_size(buffer) == 0)
+    {
+      ec = boost::system::error_code();
+      return 0;
+    }
+
+    overlapped_wrapper overlapped(ec);
+    if (ec)
+    {
+      return 0;
+    }
+
+    // Write the data. 
+    BOOL ok = ::ReadFile(impl.handle_,
+        boost::asio::buffer_cast<LPVOID>(buffer),
+        static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+    if (!ok) 
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error != ERROR_IO_PENDING)
+      {
+        if (last_error == ERROR_HANDLE_EOF)
+        {
+          ec = boost::asio::error::eof;
+        }
+        else
+        {
+          ec = boost::system::error_code(last_error,
+              boost::asio::error::get_system_category());
+        }
+        return 0;
+      }
+    }
+
+    // Wait for the operation to complete.
+    DWORD bytes_transferred = 0;
+    ok = ::GetOverlappedResult(impl.handle_,
+        &overlapped, &bytes_transferred, TRUE);
+    if (!ok)
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error == ERROR_HANDLE_EOF)
+      {
+        ec = boost::asio::error::eof;
+      }
+      else
+      {
+        ec = boost::system::error_code(last_error,
+            boost::asio::error::get_system_category());
+      }
+    }
+
+    ec = boost::system::error_code();
+    return bytes_transferred;
+  }
+
+  template <typename MutableBufferSequence, typename Handler>
+  class read_operation
+    : public operation
+  {
+  public:
+    read_operation(win_iocp_io_service& io_service,
+        const MutableBufferSequence& buffers, Handler handler)
+      : operation(io_service,
+          &read_operation<
+            MutableBufferSequence, Handler>::do_completion_impl,
+          &read_operation<
+            MutableBufferSequence, Handler>::destroy_impl),
+        work_(io_service.get_io_service()),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+  private:
+    static void do_completion_impl(operation* op,
+        DWORD last_error, size_t bytes_transferred)
+    {
+      // Take ownership of the operation object.
+      typedef read_operation<MutableBufferSequence, Handler> op_type;
+      op_type* handler_op(static_cast<op_type*>(op));
+      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+      // Check whether buffers are still valid.
+      typename MutableBufferSequence::const_iterator iter
+        = handler_op->buffers_.begin();
+      typename MutableBufferSequence::const_iterator end
+        = handler_op->buffers_.end();
+      while (iter != end)
+      {
+        boost::asio::mutable_buffer buffer(*iter);
+        boost::asio::buffer_cast<char*>(buffer);
+        ++iter;
+      }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+      // Check for the end-of-file condition.
+      boost::system::error_code ec(last_error,
+          boost::asio::error::get_system_category());
+      if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF)
+      {
+        ec = boost::asio::error::eof;
+      }
+
+      // Make a copy of the handler so that the memory can be deallocated before
+      // the upcall is made.
+      Handler handler(handler_op->handler_);
+
+      // Free the memory associated with the handler.
+      ptr.reset();
+
+      // Call the handler.
+      boost_asio_handler_invoke_helpers::invoke(
+        bind_handler(handler, ec, bytes_transferred), &handler);
+    }
+
+    static void destroy_impl(operation* op)
+    {
+      // Take ownership of the operation object.
+      typedef read_operation<MutableBufferSequence, Handler> op_type;
+      op_type* handler_op(static_cast<op_type*>(op));
+      typedef boost::asio::detail::handler_alloc_traits<
+        Handler, op_type> alloc_traits;
+      boost::asio::detail::handler_ptr<alloc_traits> ptr(
+        handler_op->handler_, handler_op);
+    }
+
+    boost::asio::io_service::work work_;
+    MutableBufferSequence buffers_;
+    Handler handler_;
+  };
+
+  // Start an asynchronous read. The buffer for the data being received must be
+  // valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename Handler>
+  void async_read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, Handler handler)
+  {
+    if (!is_open(impl))
+    {
+      this->get_io_service().post(bind_handler(handler,
+            boost::asio::error::bad_descriptor, 0));
+      return;
+    }
+
+    // Update the ID of the thread from which cancellation is safe.
+    if (impl.safe_cancellation_thread_id_ == 0)
+      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+      impl.safe_cancellation_thread_id_ = ~DWORD(0);
+
+    // Allocate and construct an operation to wrap the handler.
+    typedef read_operation<MutableBufferSequence, Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
+
+    // Find first buffer of non-zero length.
+    boost::asio::mutable_buffer buffer;
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    for (DWORD i = 0; iter != end; ++iter, ++i)
+    {
+      buffer = boost::asio::mutable_buffer(*iter);
+      if (boost::asio::buffer_size(buffer) != 0)
+        break;
+    }
+
+    // A request to receive 0 bytes on a stream handle is a no-op.
+    if (boost::asio::buffer_size(buffer) == 0)
+    {
+      boost::asio::io_service::work work(this->get_io_service());
+      ptr.reset();
+      boost::system::error_code error;
+      iocp_service_.post(bind_handler(handler, error, 0));
+      return;
+    }
+
+    // Read some data.
+    DWORD bytes_transferred = 0;
+    BOOL ok = ::ReadFile(impl.handle_,
+        boost::asio::buffer_cast<LPVOID>(buffer),
+        static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+        &bytes_transferred, ptr.get());
+    DWORD last_error = ::GetLastError();
+    if (!ok && last_error != ERROR_IO_PENDING)
+    {
+      boost::asio::io_service::work work(this->get_io_service());
+      ptr.reset();
+      boost::system::error_code ec(last_error,
+          boost::asio::error::get_system_category());
+      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+    }
+    else
+    {
+      ptr.release();
+    }
+  }
+
+private:
+  // Prevent the use of the null_buffers type with this service.
+  size_t write_some(implementation_type& impl,
+      const null_buffers& buffers, boost::system::error_code& ec);
+  template <typename Handler>
+  void async_write_some(implementation_type& impl,
+      const null_buffers& buffers, Handler handler);
+  size_t read_some(implementation_type& impl,
+      const null_buffers& buffers, boost::system::error_code& ec);
+  template <typename Handler>
+  void async_read_some(implementation_type& impl,
+      const null_buffers& buffers, Handler handler);
+
+  // Helper function to close a handle when the associated object is being
+  // destroyed.
+  void close_for_destruction(implementation_type& impl)
+  {
+    if (is_open(impl))
+    {
+      ::CloseHandle(impl.handle_);
+      impl.handle_ = INVALID_HANDLE_VALUE;
+      impl.safe_cancellation_thread_id_ = 0;
+    }
+  }
+
+  // The IOCP service used for running asynchronous operations and dispatching
+  // handlers.
+  win_iocp_io_service& iocp_service_;
+
+  // Mutex to protect access to the linked list of implementations.
+  boost::asio::detail::mutex mutex_;
+
+  // The head of a linked list of all implementations.
+  implementation_type* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_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	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -150,9 +150,20 @@
   }
 
   // Register a handle with the IO completion port.
-  void register_handle(HANDLE handle)
+  boost::system::error_code register_handle(
+      HANDLE handle, boost::system::error_code& ec)
   {
-    ::CreateIoCompletionPort(handle, iocp_.handle, 0, 0);
+    if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
+    {
+      DWORD last_error = ::GetLastError();
+      ec = boost::system::error_code(last_error,
+          boost::asio::error::get_system_category());
+    }
+    else
+    {
+      ec = boost::system::error_code();
+    }
+    return ec;
   }
 
   // Run the event loop until stopped or no more work.
Modified: trunk/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_service.hpp	(original)
+++ trunk/boost/asio/detail/win_iocp_socket_service.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -253,7 +253,8 @@
       return ec;
 
     HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
-    iocp_service_.register_handle(sock_as_handle);
+    if (iocp_service_.register_handle(sock_as_handle, ec))
+      return ec;
 
     impl.socket_ = sock.release();
     impl.flags_ = 0;
@@ -274,7 +275,8 @@
       return ec;
     }
 
-    iocp_service_.register_handle(native_socket.as_handle());
+    if (iocp_service_.register_handle(native_socket.as_handle(), ec))
+      return ec;
 
     impl.socket_ = native_socket;
     impl.flags_ = 0;
Added: trunk/boost/asio/windows/basic_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/basic_handle.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,213 @@
+//
+// basic_handle.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides Windows handle functionality.
+/**
+ * The windows::basic_handle class template provides the ability to wrap a
+ * Windows handle.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename HandleService>
+class basic_handle
+  : public basic_io_object<HandleService>
+{
+public:
+  /// The native representation of a handle.
+  typedef typename HandleService::native_type native_type;
+
+  /// A basic_handle is always the lowest layer.
+  typedef basic_handle<HandleService> lowest_layer_type;
+
+  /// Construct a basic_handle without opening it.
+  /**
+   * This constructor creates a handle without opening it.
+   *
+   * @param io_service The io_service object that the handle will use to
+   * dispatch handlers for any asynchronous operations performed on the handle.
+   */
+  explicit basic_handle(boost::asio::io_service& io_service)
+    : basic_io_object<HandleService>(io_service)
+  {
+  }
+
+  /// Construct a basic_handle on an existing native handle.
+  /**
+   * This constructor creates a handle object to hold an existing native handle.
+   *
+   * @param io_service The io_service object that the handle will use to
+   * dispatch handlers for any asynchronous operations performed on the handle.
+   *
+   * @param native_handle A native handle.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  basic_handle(boost::asio::io_service& io_service,
+      const native_type& native_handle)
+    : basic_io_object<HandleService>(io_service)
+  {
+    boost::system::error_code ec;
+    this->service.assign(this->implementation, native_handle, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Get a reference to the lowest layer.
+  /**
+   * This function returns a reference to the lowest layer in a stack of
+   * layers. Since a basic_handle cannot contain any further layers, it simply
+   * returns a reference to itself.
+   *
+   * @return A reference to the lowest layer in the stack of layers. Ownership
+   * is not transferred to the caller.
+   */
+  lowest_layer_type& lowest_layer()
+  {
+    return *this;
+  }
+
+  /// Assign an existing native handle to the handle.
+  /*
+   * This function opens the handle to hold an existing native handle.
+   *
+   * @param native_handle A native handle.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  void assign(const native_type& native_handle)
+  {
+    boost::system::error_code ec;
+    this->service.assign(this->implementation, native_handle, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Assign an existing native handle to the handle.
+  /*
+   * This function opens the handle to hold an existing native handle.
+   *
+   * @param native_handle A native handle.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  boost::system::error_code assign(const native_type& native_handle,
+      boost::system::error_code& ec)
+  {
+    return this->service.assign(this->implementation, native_handle, ec);
+  }
+
+  /// Determine whether the handle is open.
+  bool is_open() const
+  {
+    return this->service.is_open(this->implementation);
+  }
+
+  /// Close the handle.
+  /**
+   * This function is used to close the handle. Any asynchronous read or write
+   * operations will be cancelled immediately, and will complete with the
+   * boost::asio::error::operation_aborted error.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  void close()
+  {
+    boost::system::error_code ec;
+    this->service.close(this->implementation, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Close the handle.
+  /**
+   * This function is used to close the handle. Any asynchronous read or write
+   * operations will be cancelled immediately, and will complete with the
+   * boost::asio::error::operation_aborted error.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  boost::system::error_code close(boost::system::error_code& ec)
+  {
+    return this->service.close(this->implementation, ec);
+  }
+
+  /// Get the native handle representation.
+  /**
+   * This function may be used to obtain the underlying representation of the
+   * handle. This is intended to allow access to native handle functionality
+   * that is not otherwise provided.
+   */
+  native_type native()
+  {
+    return this->service.native(this->implementation);
+  }
+
+  /// Cancel all asynchronous operations associated with the handle.
+  /**
+   * This function causes all outstanding asynchronous read or write operations
+   * to finish immediately, and the handlers for cancelled operations will be
+   * passed the boost::asio::error::operation_aborted error.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  void cancel()
+  {
+    boost::system::error_code ec;
+    this->service.cancel(this->implementation, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Cancel all asynchronous operations associated with the handle.
+  /**
+   * This function causes all outstanding asynchronous read or write operations
+   * to finish immediately, and the handlers for cancelled operations will be
+   * passed the boost::asio::error::operation_aborted error.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  boost::system::error_code cancel(boost::system::error_code& ec)
+  {
+    return this->service.cancel(this->implementation, ec);
+  }
+
+protected:
+  /// Protected destructor to prevent deletion through this type.
+  ~basic_handle()
+  {
+  }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
Added: trunk/boost/asio/windows/basic_stream_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/basic_stream_handle.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,304 @@
+//
+// basic_stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/stream_handle_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides stream-oriented handle functionality.
+/**
+ * The windows::basic_stream_handle class template provides asynchronous and
+ * blocking stream-oriented handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename StreamHandleService = stream_handle_service>
+class basic_stream_handle
+  : public basic_handle<StreamHandleService>
+{
+public:
+  /// The native representation of a handle.
+  typedef typename StreamHandleService::native_type native_type;
+
+  /// Construct a basic_stream_handle without opening it.
+  /**
+   * This constructor creates a stream handle without opening it. The handle
+   * needs to be opened and then connected or accepted before data can be sent
+   * or received on it.
+   *
+   * @param io_service The io_service object that the stream handle will use to
+   * dispatch handlers for any asynchronous operations performed on the handle.
+   */
+  explicit basic_stream_handle(boost::asio::io_service& io_service)
+    : basic_handle<StreamHandleService>(io_service)
+  {
+  }
+
+  /// Construct a basic_stream_handle on an existing native handle.
+  /**
+   * This constructor creates a stream handle object to hold an existing native
+   * handle.
+   *
+   * @param io_service The io_service object that the stream 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_stream_handle(boost::asio::io_service& io_service,
+      const native_type& native_handle)
+    : basic_handle<StreamHandleService>(io_service, native_handle)
+  {
+  }
+
+  /// Write some data to the handle.
+  /**
+   * This function is used to write data to the stream handle. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the handle.
+   *
+   * @returns The number of bytes written.
+   *
+   * @throws boost::system::system_error Thrown on failure. An error code of
+   * boost::asio::error::eof indicates that the connection was closed by the
+   * peer.
+   *
+   * @note The write_some operation may not transmit all of the data to the
+   * peer. Consider using the @ref write function if you need to ensure that
+   * all data is written before the blocking operation completes.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * handle.write_some(boost::asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    boost::system::error_code ec;
+    std::size_t s = this->service.write_some(this->implementation, buffers, ec);
+    boost::asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Write some data to the handle.
+  /**
+   * This function is used to write data to the stream handle. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the handle.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes written. Returns 0 if an error occurred.
+   *
+   * @note The write_some operation may not transmit all of the data to the
+   * peer. Consider using the @ref write function if you need to ensure that
+   * all data is written before the blocking operation completes.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers,
+      boost::system::error_code& ec)
+  {
+    return this->service.write_some(this->implementation, buffers, ec);
+  }
+
+  /// Start an asynchronous write.
+  /**
+   * This function is used to asynchronously write data to the stream handle.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be written to the handle.
+   * Although the buffers object may be copied as necessary, ownership of the
+   * underlying memory blocks is retained by the caller, which must guarantee
+   * that they remain valid until the handler is called.
+   *
+   * @param handler The handler to be called when the write operation completes.
+   * 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.
+   *   std::size_t bytes_transferred           // Number of bytes written.
+   * ); @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().
+   *
+   * @note The write operation may not transmit all of the data to the peer.
+   * Consider using the @ref async_write function if you need to ensure that all
+   * data is written before the asynchronous operation completes.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * handle.async_write_some(boost::asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    this->service.async_write_some(this->implementation, buffers, handler);
+  }
+
+  /// Read some data from the handle.
+  /**
+   * This function is used to read data from the stream handle. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @returns The number of bytes read.
+   *
+   * @throws boost::system::system_error Thrown on failure. An error code of
+   * boost::asio::error::eof indicates that the connection was closed by the
+   * peer.
+   *
+   * @note The read_some operation may not read all of the requested number of
+   * bytes. Consider using the @ref read function if you need to ensure that
+   * the requested amount of data is read before the blocking operation
+   * completes.
+   *
+   * @par Example
+   * To read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * handle.read_some(boost::asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on reading into multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    boost::system::error_code ec;
+    std::size_t s = this->service.read_some(this->implementation, buffers, ec);
+    boost::asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Read some data from the handle.
+  /**
+   * This function is used to read data from the stream handle. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes read. Returns 0 if an error occurred.
+   *
+   * @note The read_some operation may not read all of the requested number of
+   * bytes. Consider using the @ref read function if you need to ensure that
+   * the requested amount of data is read before the blocking operation
+   * completes.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers,
+      boost::system::error_code& ec)
+  {
+    return this->service.read_some(this->implementation, buffers, ec);
+  }
+
+  /// Start an asynchronous read.
+  /**
+   * This function is used to asynchronously read data from the stream handle.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   * Although the buffers object may be copied as necessary, ownership of the
+   * underlying memory blocks is retained by the caller, which must guarantee
+   * that they remain valid until the handler is called.
+   *
+   * @param handler The handler to be called when the read operation completes.
+   * 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.
+   *   std::size_t bytes_transferred           // Number of bytes read.
+   * ); @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().
+   *
+   * @note The read operation may not read all of the requested number of bytes.
+   * Consider using the @ref async_read function if you need to ensure that the
+   * requested amount of data is read before the asynchronous operation
+   * completes.
+   *
+   * @par Example
+   * To read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * handle.async_read_some(boost::asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on reading into multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    this->service.async_read_some(this->implementation, buffers, handler);
+  }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
Added: trunk/boost/asio/windows/stream_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/stream_handle.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,41 @@
+//
+// stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/windows/basic_stream_handle.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Typedef for the typical usage of a stream-oriented handle.
+typedef basic_stream_handle<> stream_handle;
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
Added: trunk/boost/asio/windows/stream_handle_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/windows/stream_handle_service.hpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,179 @@
+//
+// stream_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/win_iocp_handle_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+# if defined(BOOST_ASIO_HAS_IOCP)
+#  define BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE 1
+# endif // defined(BOOST_ASIO_HAS_IOCP)
+#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Default service implementation for a stream handle.
+class stream_handle_service
+#if defined(GENERATING_DOCUMENTATION)
+  : public boost::asio::io_service::service
+#else
+  : public boost::asio::detail::service_base<stream_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_iocp_handle_service service_impl_type;
+
+public:
+  /// The type of a stream 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_type;
+#else
+  typedef service_impl_type::native_type native_type;
+#endif
+
+  /// Construct a new stream handle service for the specified io_service.
+  explicit stream_handle_service(boost::asio::io_service& io_service)
+    : boost::asio::detail::service_base<stream_handle_service>(io_service),
+      service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+  {
+  }
+
+  /// Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+  }
+
+  /// Construct a new stream handle implementation.
+  void construct(implementation_type& impl)
+  {
+    service_impl_.construct(impl);
+  }
+
+  /// Destroy a stream handle implementation.
+  void destroy(implementation_type& impl)
+  {
+    service_impl_.destroy(impl);
+  }
+
+  /// Assign an existing native handle to a stream handle.
+  boost::system::error_code assign(implementation_type& impl,
+      const native_type& native_handle, boost::system::error_code& ec)
+  {
+    return service_impl_.assign(impl, native_handle, ec);
+  }
+
+  /// Determine whether the handle is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return service_impl_.is_open(impl);
+  }
+
+  /// Close a stream 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_type native(implementation_type& impl)
+  {
+    return service_impl_.native(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);
+  }
+
+  /// Write the given data to the stream.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, boost::system::error_code& ec)
+  {
+    return service_impl_.write_some(impl, buffers, ec);
+  }
+
+  /// Start an asynchronous write.
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, WriteHandler handler)
+  {
+    service_impl_.async_write_some(impl, buffers, handler);
+  }
+
+  /// Read some data from the stream.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, boost::system::error_code& ec)
+  {
+    return service_impl_.read_some(impl, buffers, ec);
+  }
+
+  /// Start an asynchronous read.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, ReadHandler handler)
+  {
+    service_impl_.async_read_some(impl, buffers, handler);
+  }
+
+private:
+  // The service that provides the platform-specific implementation.
+  service_impl_type& service_impl_;
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
Modified: trunk/libs/asio/test/Jamfile
==============================================================================
--- trunk/libs/asio/test/Jamfile	(original)
+++ trunk/libs/asio/test/Jamfile	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -86,5 +86,9 @@
   [ run strand.cpp <template>asio_unit_test ]
   [ run stream_socket_service.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_stream_handle.cpp <template>asio_unit_test ]
+  [ run windows/stream_handle.cpp <template>asio_unit_test ]
+  [ run windows/stream_handle_service.cpp <template>asio_unit_test ]
   [ run write.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	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -150,6 +150,14 @@
   [ link stream_socket_service.cpp : $(USE_SELECT) : stream_socket_service_select ]
   [ link time_traits.cpp ]
   [ link time_traits.cpp : $(USE_SELECT) : time_traits_select ]
+  [ link windows/basic_handle.cpp : : windows_basic_handle ]
+  [ link windows/basic_handle.cpp : $(USE_SELECT) : windows_basic_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/stream_handle.cpp : : windows_stream_handle ]
+  [ link windows/stream_handle.cpp : $(USE_SELECT) : windows_stream_handle_select ]
+  [ link windows/stream_handle_service.cpp : : windows_stream_handle_service ]
+  [ link windows/stream_handle_service.cpp : $(USE_SELECT) : windows_stream_handle_service_select ]
   [ run write.cpp ]
   [ run write.cpp : : : $(USE_SELECT) : write_select ]
   ;
Added: trunk/libs/asio/test/windows/basic_handle.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/basic_handle.cpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// basic_handle.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// 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_handle.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/basic_handle");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/windows/basic_stream_handle.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/basic_stream_handle.cpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// basic_stream_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// 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_stream_handle.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/basic_stream_handle");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/windows/stream_handle.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/stream_handle.cpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,114 @@
+//
+// stream_handle.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// 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/stream_handle.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_stream_handle_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::stream_handle compile and link correctly. Runtime failures are
+// ignored.
+
+namespace windows_stream_handle_compile {
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+  using namespace boost::asio;
+  namespace win = boost::asio::windows;
+
+  try
+  {
+    io_service ios;
+    char mutable_char_buffer[128] = "";
+    const char const_char_buffer[128] = "";
+    boost::system::error_code ec;
+
+    // basic_stream_handle constructors.
+
+    win::stream_handle handle1(ios);
+    HANDLE native_handle1 = INVALID_HANDLE_VALUE;
+    win::stream_handle handle2(ios, native_handle1);
+
+    // basic_io_object functions.
+
+    io_service& ios_ref = handle1.io_service();
+    (void)ios_ref;
+
+    // basic_handle functions.
+
+    win::stream_handle::lowest_layer_type& lowest_layer
+      = handle1.lowest_layer();
+    (void)lowest_layer;
+
+    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::stream_handle::native_type native_handle3 = handle1.native();
+    (void)native_handle3;
+
+    handle1.cancel();
+    handle1.cancel(ec);
+
+    // basic_stream_handle functions.
+
+    handle1.write_some(buffer(mutable_char_buffer));
+    handle1.write_some(buffer(const_char_buffer));
+    handle1.write_some(buffer(mutable_char_buffer), ec);
+    handle1.write_some(buffer(const_char_buffer), ec);
+
+    handle1.async_write_some(buffer(mutable_char_buffer), write_some_handler);
+    handle1.async_write_some(buffer(const_char_buffer), write_some_handler);
+
+    handle1.read_some(buffer(mutable_char_buffer));
+    handle1.read_some(buffer(mutable_char_buffer), ec);
+
+    handle1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+  }
+  catch (std::exception&)
+  {
+  }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+}
+
+} // namespace windows_stream_handle_compile
+
+//------------------------------------------------------------------------------
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/stream_handle");
+  test->add(BOOST_TEST_CASE(&windows_stream_handle_compile::test));
+  return test;
+}
Added: trunk/libs/asio/test/windows/stream_handle_service.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/windows/stream_handle_service.cpp	2008-04-21 01:32:34 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// stream_handle_service.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// 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/stream_handle_service.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+  test_suite* test = BOOST_TEST_SUITE("windows/stream_handle_service");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}