Boost logo

Boost-Commit :

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;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk