$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: chris_at_[hidden]
Date: 2008-04-21 01:16:16
Author: chris_kohlhoff
Date: 2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
New Revision: 44675
URL: http://svn.boost.org/trac/boost/changeset/44675
Log:
Add new wrapper classes for stream-oriented file descriptors on POSIX platforms.
Added:
   trunk/boost/asio/detail/descriptor_ops.hpp   (contents, props changed)
   trunk/boost/asio/detail/reactive_descriptor_service.hpp   (contents, props changed)
   trunk/boost/asio/posix/
   trunk/boost/asio/posix/basic_descriptor.hpp   (contents, props changed)
   trunk/boost/asio/posix/basic_stream_descriptor.hpp   (contents, props changed)
   trunk/boost/asio/posix/descriptor_base.hpp   (contents, props changed)
   trunk/boost/asio/posix/stream_descriptor.hpp   (contents, props changed)
   trunk/boost/asio/posix/stream_descriptor_service.hpp   (contents, props changed)
   trunk/libs/asio/test/posix/
   trunk/libs/asio/test/posix/basic_descriptor.cpp   (contents, props changed)
   trunk/libs/asio/test/posix/basic_stream_descriptor.cpp   (contents, props changed)
   trunk/libs/asio/test/posix/descriptor_base.cpp   (contents, props changed)
   trunk/libs/asio/test/posix/stream_descriptor.cpp   (contents, props changed)
   trunk/libs/asio/test/posix/stream_descriptor_service.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/asio.hpp            |     5 +++++                                   
   trunk/libs/asio/test/Jamfile    |     5 +++++                                   
   trunk/libs/asio/test/Jamfile.v2 |    10 ++++++++++                              
   3 files changed, 20 insertions(+), 0 deletions(-)
Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp	(original)
+++ trunk/boost/asio.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -63,6 +63,11 @@
 #include <boost/asio/local/datagram_protocol.hpp>
 #include <boost/asio/local/stream_protocol.hpp>
 #include <boost/asio/placeholders.hpp>
+#include <boost/asio/posix/basic_descriptor.hpp>
+#include <boost/asio/posix/basic_stream_descriptor.hpp>
+#include <boost/asio/posix/descriptor_base.hpp>
+#include <boost/asio/posix/stream_descriptor.hpp>
+#include <boost/asio/posix/stream_descriptor_service.hpp>
 #include <boost/asio/read.hpp>
 #include <boost/asio/read_until.hpp>
 #include <boost/asio/socket_acceptor_service.hpp>
Added: trunk/boost/asio/detail/descriptor_ops.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/descriptor_ops.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,121 @@
+//
+// descriptor_ops.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_DETAIL_DESCRIPTOR_OPS_HPP
+#define BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_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 <cerrno>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace descriptor_ops {
+
+inline void clear_error(boost::system::error_code& ec)
+{
+  errno = 0;
+  ec = boost::system::error_code();
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+    boost::system::error_code& ec)
+{
+  ec = boost::system::error_code(errno,
+      boost::asio::error::get_system_category());
+  return return_value;
+}
+
+inline int close(int d, boost::system::error_code& ec)
+{
+  clear_error(ec);
+  return error_wrapper(::close(d), ec);
+}
+
+typedef iovec buf;
+
+inline void init_buf(buf& b, void* data, size_t size)
+{
+  b.iov_base = data;
+  b.iov_len = size;
+}
+
+inline void init_buf(buf& b, const void* data, size_t size)
+{
+  b.iov_base = const_cast<void*>(data);
+  b.iov_len = size;
+}
+
+inline int readv(int d, buf* bufs, size_t count, boost::system::error_code& ec)
+{
+  clear_error(ec);
+  return error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+}
+
+inline int writev(int d, const buf* bufs, size_t count,
+    boost::system::error_code& ec)
+{
+  clear_error(ec);
+  return error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+}
+
+inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
+    boost::system::error_code& ec)
+{
+  clear_error(ec);
+  return error_wrapper(::ioctl(d, cmd, arg), ec);
+}
+
+inline int poll_read(int d, boost::system::error_code& ec)
+{
+  clear_error(ec);
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLIN;
+  fds.revents = 0;
+  clear_error(ec);
+  return error_wrapper(::poll(&fds, 1, -1), ec);
+}
+
+inline int poll_write(int d, boost::system::error_code& ec)
+{
+  clear_error(ec);
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  clear_error(ec);
+  return error_wrapper(::poll(&fds, 1, -1), ec);
+}
+
+} // namespace descriptor_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP
Added: trunk/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/reactive_descriptor_service.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,684 @@
+//
+// reactive_descriptor_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_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_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/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/descriptor_ops.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Reactor>
+class reactive_descriptor_service
+  : public boost::asio::detail::service_base<
+      reactive_descriptor_service<Reactor> >
+{
+public:
+  // The native type of a descriptor.
+  typedef int native_type;
+
+  // The implementation type of the descriptor.
+  class implementation_type
+    : private boost::asio::detail::noncopyable
+  {
+  public:
+    // Default constructor.
+    implementation_type()
+      : descriptor_(-1),
+        flags_(0)
+    {
+    }
+
+  private:
+    // Only this service will have access to the internal values.
+    friend class reactive_descriptor_service<Reactor>;
+
+    // The native descriptor representation.
+    int descriptor_;
+
+    enum
+    {
+      user_set_non_blocking = 1, // The user wants a non-blocking descriptor.
+      internal_non_blocking = 2  // The descriptor has been set non-blocking.
+    };
+
+    // Flags indicating the current state of the descriptor.
+    unsigned char flags_;
+  };
+
+  // The maximum number of buffers to support in a single operation.
+  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+  // Constructor.
+  reactive_descriptor_service(boost::asio::io_service& io_service)
+    : boost::asio::detail::service_base<
+        reactive_descriptor_service<Reactor> >(io_service),
+      reactor_(boost::asio::use_service<Reactor>(io_service))
+  {
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+  }
+
+  // Construct a new descriptor implementation.
+  void construct(implementation_type& impl)
+  {
+    impl.descriptor_ = -1;
+    impl.flags_ = 0;
+  }
+
+  // Destroy a descriptor implementation.
+  void destroy(implementation_type& impl)
+  {
+    if (impl.descriptor_ != -1)
+    {
+      reactor_.close_descriptor(impl.descriptor_);
+
+      if (impl.flags_ & implementation_type::internal_non_blocking)
+      {
+        ioctl_arg_type non_blocking = 0;
+        boost::system::error_code ignored_ec;
+        descriptor_ops::ioctl(impl.descriptor_,
+            FIONBIO, &non_blocking, ignored_ec);
+        impl.flags_ &= ~implementation_type::internal_non_blocking;
+      }
+
+      boost::system::error_code ignored_ec;
+      descriptor_ops::close(impl.descriptor_, ignored_ec);
+
+      impl.descriptor_ = -1;
+    }
+  }
+
+  // Assign a native descriptor to a descriptor implementation.
+  boost::system::error_code assign(implementation_type& impl,
+      const native_type& native_descriptor, boost::system::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      ec = boost::asio::error::already_open;
+      return ec;
+    }
+
+    if (int err = reactor_.register_descriptor(native_descriptor))
+    {
+      ec = boost::system::error_code(err,
+          boost::asio::error::get_system_category());
+      return ec;
+    }
+
+    impl.descriptor_ = native_descriptor;
+    impl.flags_ = 0;
+    ec = boost::system::error_code();
+    return ec;
+  }
+
+  // Determine whether the descriptor is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return impl.descriptor_ != -1;
+  }
+
+  // Destroy a descriptor implementation.
+  boost::system::error_code close(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      reactor_.close_descriptor(impl.descriptor_);
+
+      if (impl.flags_ & implementation_type::internal_non_blocking)
+      {
+        ioctl_arg_type non_blocking = 0;
+        boost::system::error_code ignored_ec;
+        descriptor_ops::ioctl(impl.descriptor_,
+            FIONBIO, &non_blocking, ignored_ec);
+        impl.flags_ &= ~implementation_type::internal_non_blocking;
+      }
+
+      if (descriptor_ops::close(impl.descriptor_, ec) == -1)
+        return ec;
+
+      impl.descriptor_ = -1;
+    }
+
+    ec = boost::system::error_code();
+    return ec;
+  }
+
+  // Get the native descriptor representation.
+  native_type native(implementation_type& impl)
+  {
+    return impl.descriptor_;
+  }
+
+  // Cancel all operations associated with the descriptor.
+  boost::system::error_code cancel(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return ec;
+    }
+
+    reactor_.cancel_ops(impl.descriptor_);
+    ec = boost::system::error_code();
+    return ec;
+  }
+
+  // Perform an IO control command on the descriptor.
+  template <typename IO_Control_Command>
+  boost::system::error_code io_control(implementation_type& impl,
+      IO_Control_Command& command, boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return ec;
+    }
+
+    if (command.name() == static_cast<int>(FIONBIO))
+    {
+      if (command.get())
+        impl.flags_ |= implementation_type::user_set_non_blocking;
+      else
+        impl.flags_ &= ~implementation_type::user_set_non_blocking;
+      ec = boost::system::error_code();
+    }
+    else
+    {
+      descriptor_ops::ioctl(impl.descriptor_, command.name(),
+          static_cast<ioctl_arg_type*>(command.data()), ec);
+    }
+    return ec;
+  }
+
+  // Write some data to the descriptor.
+  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;
+    }
+
+    // Copy buffers into array.
+    descriptor_ops::buf bufs[max_buffers];
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    size_t i = 0;
+    size_t total_buffer_size = 0;
+    for (; iter != end && i < max_buffers; ++iter, ++i)
+    {
+      boost::asio::const_buffer buffer(*iter);
+      descriptor_ops::init_buf(bufs[i],
+          boost::asio::buffer_cast<const void*>(buffer),
+          boost::asio::buffer_size(buffer));
+      total_buffer_size += boost::asio::buffer_size(buffer);
+    }
+
+    // A request to read_some 0 bytes on a stream is a no-op.
+    if (total_buffer_size == 0)
+    {
+      ec = boost::system::error_code();
+      return 0;
+    }
+
+    // Make descriptor non-blocking if user wants non-blocking.
+    if (impl.flags_ & implementation_type::user_set_non_blocking)
+    {
+      if (!(impl.flags_ & implementation_type::internal_non_blocking))
+      {
+        ioctl_arg_type non_blocking = 1;
+        if (descriptor_ops::ioctl(impl.descriptor_,
+              FIONBIO, &non_blocking, ec))
+          return 0;
+        impl.flags_ |= implementation_type::internal_non_blocking;
+      }
+    }
+
+    // Send the data.
+    for (;;)
+    {
+      // Try to complete the operation without blocking.
+      int bytes_sent = descriptor_ops::writev(impl.descriptor_, bufs, i, ec);
+
+      // Check if operation succeeded.
+      if (bytes_sent >= 0)
+        return bytes_sent;
+
+      // Operation failed.
+      if ((impl.flags_ & implementation_type::user_set_non_blocking)
+          || (ec != boost::asio::error::would_block
+            && ec != boost::asio::error::try_again))
+        return 0;
+
+      // Wait for descriptor to become ready.
+      if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0)
+        return 0;
+    }
+  }
+
+  // Wait until data can be written without blocking.
+  size_t write_some(implementation_type& impl,
+      const null_buffers&, boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return 0;
+    }
+
+    // Wait for descriptor to become ready.
+    descriptor_ops::poll_write(impl.descriptor_, ec);
+
+    return 0;
+  }
+
+  template <typename ConstBufferSequence, typename Handler>
+  class write_handler
+  {
+  public:
+    write_handler(int descriptor, boost::asio::io_service& io_service,
+        const ConstBufferSequence& buffers, Handler handler)
+      : descriptor_(descriptor),
+        io_service_(io_service),
+        work_(io_service),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+    bool operator()(const boost::system::error_code& result)
+    {
+      // Check whether the operation was successful.
+      if (result)
+      {
+        io_service_.post(bind_handler(handler_, result, 0));
+        return true;
+      }
+
+      // Copy buffers into array.
+      descriptor_ops::buf bufs[max_buffers];
+      typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+      typename ConstBufferSequence::const_iterator end = buffers_.end();
+      size_t i = 0;
+      for (; iter != end && i < max_buffers; ++iter, ++i)
+      {
+        boost::asio::const_buffer buffer(*iter);
+        descriptor_ops::init_buf(bufs[i],
+            boost::asio::buffer_cast<const void*>(buffer),
+            boost::asio::buffer_size(buffer));
+      }
+
+      // Write the data.
+      boost::system::error_code ec;
+      int bytes = descriptor_ops::writev(descriptor_, bufs, i, ec);
+
+      // Check if we need to run the operation again.
+      if (ec == boost::asio::error::would_block
+          || ec == boost::asio::error::try_again)
+        return false;
+
+      io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+      return true;
+    }
+
+  private:
+    int descriptor_;
+    boost::asio::io_service& io_service_;
+    boost::asio::io_service::work work_;
+    ConstBufferSequence buffers_;
+    Handler handler_;
+  };
+
+  // Start an asynchronous write. The data being sent must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, Handler handler)
+  {
+    if (!is_open(impl))
+    {
+      this->get_io_service().post(bind_handler(handler,
+            boost::asio::error::bad_descriptor, 0));
+    }
+    else
+    {
+      // Determine total size of buffers.
+      typename ConstBufferSequence::const_iterator iter = buffers.begin();
+      typename ConstBufferSequence::const_iterator end = buffers.end();
+      size_t i = 0;
+      size_t total_buffer_size = 0;
+      for (; iter != end && i < max_buffers; ++iter, ++i)
+      {
+        boost::asio::const_buffer buffer(*iter);
+        total_buffer_size += boost::asio::buffer_size(buffer);
+      }
+
+      // A request to read_some 0 bytes on a stream is a no-op.
+      if (total_buffer_size == 0)
+      {
+        this->get_io_service().post(bind_handler(handler,
+              boost::system::error_code(), 0));
+        return;
+      }
+
+      // Make descriptor non-blocking.
+      if (!(impl.flags_ & implementation_type::internal_non_blocking))
+      {
+        ioctl_arg_type non_blocking = 1;
+        boost::system::error_code ec;
+        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+        {
+          this->get_io_service().post(bind_handler(handler, ec, 0));
+          return;
+        }
+        impl.flags_ |= implementation_type::internal_non_blocking;
+      }
+
+      reactor_.start_write_op(impl.descriptor_,
+          write_handler<ConstBufferSequence, Handler>(
+            impl.descriptor_, this->get_io_service(), buffers, handler));
+    }
+  }
+
+  template <typename Handler>
+  class null_buffers_handler
+  {
+  public:
+    null_buffers_handler(boost::asio::io_service& io_service, Handler handler)
+      : work_(io_service),
+        handler_(handler)
+    {
+    }
+
+    bool operator()(const boost::system::error_code& result)
+    {
+      work_.get_io_service().post(bind_handler(handler_, result, 0));
+      return true;
+    }
+
+  private:
+    boost::asio::io_service::work work_;
+    Handler handler_;
+  };
+
+  // Start an asynchronous wait until data can be written without blocking.
+  template <typename Handler>
+  void async_write_some(implementation_type& impl,
+      const null_buffers&, Handler handler)
+  {
+    if (!is_open(impl))
+    {
+      this->get_io_service().post(bind_handler(handler,
+            boost::asio::error::bad_descriptor, 0));
+    }
+    else
+    {
+      reactor_.start_write_op(impl.descriptor_,
+          null_buffers_handler<Handler>(this->get_io_service(), handler),
+          false);
+    }
+  }
+
+  // Read some data from the stream. Returns the number of bytes read.
+  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;
+    }
+
+    // Copy buffers into array.
+    descriptor_ops::buf bufs[max_buffers];
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    size_t i = 0;
+    size_t total_buffer_size = 0;
+    for (; iter != end && i < max_buffers; ++iter, ++i)
+    {
+      boost::asio::mutable_buffer buffer(*iter);
+      descriptor_ops::init_buf(bufs[i],
+          boost::asio::buffer_cast<void*>(buffer),
+          boost::asio::buffer_size(buffer));
+      total_buffer_size += boost::asio::buffer_size(buffer);
+    }
+
+    // A request to read_some 0 bytes on a stream is a no-op.
+    if (total_buffer_size == 0)
+    {
+      ec = boost::system::error_code();
+      return 0;
+    }
+
+    // Make descriptor non-blocking if user wants non-blocking.
+    if (impl.flags_ & implementation_type::user_set_non_blocking)
+    {
+      if (!(impl.flags_ & implementation_type::internal_non_blocking))
+      {
+        ioctl_arg_type non_blocking = 1;
+        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+          return 0;
+        impl.flags_ |= implementation_type::internal_non_blocking;
+      }
+    }
+
+    // Read some data.
+    for (;;)
+    {
+      // Try to complete the operation without blocking.
+      int bytes_read = descriptor_ops::readv(impl.descriptor_, bufs, i, ec);
+
+      // Check if operation succeeded.
+      if (bytes_read > 0)
+        return bytes_read;
+
+      // Check for EOF.
+      if (bytes_read == 0)
+      {
+        ec = boost::asio::error::eof;
+        return 0;
+      }
+
+      // Operation failed.
+      if ((impl.flags_ & implementation_type::user_set_non_blocking)
+          || (ec != boost::asio::error::would_block
+            && ec != boost::asio::error::try_again))
+        return 0;
+
+      // Wait for descriptor to become ready.
+      if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0)
+        return 0;
+    }
+  }
+
+  // Wait until data can be read without blocking.
+  size_t read_some(implementation_type& impl,
+      const null_buffers& buffers, boost::system::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = boost::asio::error::bad_descriptor;
+      return 0;
+    }
+
+    // Wait for descriptor to become ready.
+    descriptor_ops::poll_read(impl.descriptor_, ec);
+
+    return 0;
+  }
+
+  template <typename MutableBufferSequence, typename Handler>
+  class read_handler
+  {
+  public:
+    read_handler(int descriptor, boost::asio::io_service& io_service,
+        const MutableBufferSequence& buffers, Handler handler)
+      : descriptor_(descriptor),
+        io_service_(io_service),
+        work_(io_service),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+    bool operator()(const boost::system::error_code& result)
+    {
+      // Check whether the operation was successful.
+      if (result)
+      {
+        io_service_.post(bind_handler(handler_, result, 0));
+        return true;
+      }
+
+      // Copy buffers into array.
+      descriptor_ops::buf bufs[max_buffers];
+      typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+      typename MutableBufferSequence::const_iterator end = buffers_.end();
+      size_t i = 0;
+      for (; iter != end && i < max_buffers; ++iter, ++i)
+      {
+        boost::asio::mutable_buffer buffer(*iter);
+        descriptor_ops::init_buf(bufs[i],
+            boost::asio::buffer_cast<void*>(buffer),
+            boost::asio::buffer_size(buffer));
+      }
+
+      // Read some data.
+      boost::system::error_code ec;
+      int bytes = descriptor_ops::readv(descriptor_, bufs, i, ec);
+      if (bytes == 0)
+        ec = boost::asio::error::eof;
+
+      // Check if we need to run the operation again.
+      if (ec == boost::asio::error::would_block
+          || ec == boost::asio::error::try_again)
+        return false;
+
+      io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes));
+      return true;
+    }
+
+  private:
+    int descriptor_;
+    boost::asio::io_service& io_service_;
+    boost::asio::io_service::work work_;
+    MutableBufferSequence buffers_;
+    Handler handler_;
+  };
+
+  // Start an asynchronous read. The buffer for the data being read must be
+  // 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));
+    }
+    else
+    {
+      // Determine total size of buffers.
+      typename MutableBufferSequence::const_iterator iter = buffers.begin();
+      typename MutableBufferSequence::const_iterator end = buffers.end();
+      size_t i = 0;
+      size_t total_buffer_size = 0;
+      for (; iter != end && i < max_buffers; ++iter, ++i)
+      {
+        boost::asio::mutable_buffer buffer(*iter);
+        total_buffer_size += boost::asio::buffer_size(buffer);
+      }
+
+      // A request to read_some 0 bytes on a stream is a no-op.
+      if (total_buffer_size == 0)
+      {
+        this->get_io_service().post(bind_handler(handler,
+              boost::system::error_code(), 0));
+        return;
+      }
+
+      // Make descriptor non-blocking.
+      if (!(impl.flags_ & implementation_type::internal_non_blocking))
+      {
+        ioctl_arg_type non_blocking = 1;
+        boost::system::error_code ec;
+        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+        {
+          this->get_io_service().post(bind_handler(handler, ec, 0));
+          return;
+        }
+        impl.flags_ |= implementation_type::internal_non_blocking;
+      }
+
+      reactor_.start_read_op(impl.descriptor_,
+          read_handler<MutableBufferSequence, Handler>(
+            impl.descriptor_, this->get_io_service(), buffers, handler));
+    }
+  }
+
+  // Wait until data can be read without blocking.
+  template <typename Handler>
+  void async_read_some(implementation_type& impl,
+      const null_buffers&, Handler handler)
+  {
+    if (!is_open(impl))
+    {
+      this->get_io_service().post(bind_handler(handler,
+            boost::asio::error::bad_descriptor, 0));
+    }
+    else
+    {
+      reactor_.start_read_op(impl.descriptor_,
+          null_buffers_handler<Handler>(this->get_io_service(), handler),
+          false);
+    }
+  }
+
+private:
+  // The selector that performs event demultiplexing for the service.
+  Reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
Added: trunk/boost/asio/posix/basic_descriptor.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/posix/basic_descriptor.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,282 @@
+//
+// basic_descriptor.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_POSIX_BASIC_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_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/posix/descriptor_base.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Provides POSIX descriptor functionality.
+/**
+ * The posix::basic_descriptor class template provides the ability to wrap a
+ * POSIX descriptor.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename DescriptorService>
+class basic_descriptor
+  : public basic_io_object<DescriptorService>,
+    public descriptor_base
+{
+public:
+  /// The native representation of a descriptor.
+  typedef typename DescriptorService::native_type native_type;
+
+  /// A basic_descriptor is always the lowest layer.
+  typedef basic_descriptor<DescriptorService> lowest_layer_type;
+
+  /// Construct a basic_descriptor without opening it.
+  /**
+   * This constructor creates a descriptor without opening it.
+   *
+   * @param io_service The io_service object that the descriptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * descriptor.
+   */
+  explicit basic_descriptor(boost::asio::io_service& io_service)
+    : basic_io_object<DescriptorService>(io_service)
+  {
+  }
+
+  /// Construct a basic_descriptor on an existing native descriptor.
+  /**
+   * This constructor creates a descriptor object to hold an existing native
+   * descriptor.
+   *
+   * @param io_service The io_service object that the descriptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * descriptor.
+   *
+   * @param native_descriptor A native descriptor.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  basic_descriptor(boost::asio::io_service& io_service,
+      const native_type& native_descriptor)
+    : basic_io_object<DescriptorService>(io_service)
+  {
+    boost::system::error_code ec;
+    this->service.assign(this->implementation, native_descriptor, 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_descriptor 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 descriptor to the descriptor.
+  /*
+   * This function opens the descriptor to hold an existing native descriptor.
+   *
+   * @param native_descriptor A native descriptor.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  void assign(const native_type& native_descriptor)
+  {
+    boost::system::error_code ec;
+    this->service.assign(this->implementation, native_descriptor, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Assign an existing native descriptor to the descriptor.
+  /*
+   * This function opens the descriptor to hold an existing native descriptor.
+   *
+   * @param native_descriptor A native descriptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  boost::system::error_code assign(const native_type& native_descriptor,
+      boost::system::error_code& ec)
+  {
+    return this->service.assign(this->implementation, native_descriptor, ec);
+  }
+
+  /// Determine whether the descriptor is open.
+  bool is_open() const
+  {
+    return this->service.is_open(this->implementation);
+  }
+
+  /// Close the descriptor.
+  /**
+   * This function is used to close the descriptor. 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 descriptor.
+  /**
+   * This function is used to close the descriptor. 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 descriptor representation.
+  /**
+   * This function may be used to obtain the underlying representation of the
+   * descriptor. This is intended to allow access to native descriptor
+   * functionality that is not otherwise provided.
+   */
+  native_type native()
+  {
+    return this->service.native(this->implementation);
+  }
+
+  /// Cancel all asynchronous operations associated with the descriptor.
+  /**
+   * 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 descriptor.
+  /**
+   * 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);
+  }
+
+  /// Perform an IO control command on the descriptor.
+  /**
+   * This function is used to execute an IO control command on the descriptor.
+   *
+   * @param command The IO control command to be performed on the descriptor.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   *
+   * @sa IoControlCommand @n
+   * boost::asio::posix::descriptor_base::bytes_readable @n
+   * boost::asio::posix::descriptor_base::non_blocking_io
+   *
+   * @par Example
+   * Getting the number of bytes ready to read:
+   * @code
+   * boost::asio::posix::stream_descriptor descriptor(io_service);
+   * ...
+   * boost::asio::posix::stream_descriptor::bytes_readable command;
+   * descriptor.io_control(command);
+   * std::size_t bytes_readable = command.get();
+   * @endcode
+   */
+  template <typename IoControlCommand>
+  void io_control(IoControlCommand& command)
+  {
+    boost::system::error_code ec;
+    this->service.io_control(this->implementation, command, ec);
+    boost::asio::detail::throw_error(ec);
+  }
+
+  /// Perform an IO control command on the descriptor.
+  /**
+   * This function is used to execute an IO control command on the descriptor.
+   *
+   * @param command The IO control command to be performed on the descriptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @sa IoControlCommand @n
+   * boost::asio::posix::descriptor_base::bytes_readable @n
+   * boost::asio::posix::descriptor_base::non_blocking_io
+   *
+   * @par Example
+   * Getting the number of bytes ready to read:
+   * @code
+   * boost::asio::posix::stream_descriptor descriptor(io_service);
+   * ...
+   * boost::asio::posix::stream_descriptor::bytes_readable command;
+   * boost::system::error_code ec;
+   * descriptor.io_control(command, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * std::size_t bytes_readable = command.get();
+   * @endcode
+   */
+  template <typename IoControlCommand>
+  boost::system::error_code io_control(IoControlCommand& command,
+      boost::system::error_code& ec)
+  {
+    return this->service.io_control(this->implementation, command, ec);
+  }
+
+protected:
+  /// Protected destructor to prevent deletion through this type.
+  ~basic_descriptor()
+  {
+  }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
Added: trunk/boost/asio/posix/basic_stream_descriptor.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/posix/basic_stream_descriptor.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,306 @@
+//
+// basic_stream_descriptor.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_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_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/posix/basic_descriptor.hpp>
+#include <boost/asio/posix/stream_descriptor_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Provides stream-oriented descriptor functionality.
+/**
+ * The posix::basic_stream_descriptor class template provides asynchronous and
+ * blocking stream-oriented descriptor 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 StreamDescriptorService = stream_descriptor_service>
+class basic_stream_descriptor
+  : public basic_descriptor<StreamDescriptorService>
+{
+public:
+  /// The native representation of a descriptor.
+  typedef typename StreamDescriptorService::native_type native_type;
+
+  /// Construct a basic_stream_descriptor without opening it.
+  /**
+   * This constructor creates a stream descriptor without opening it. The
+   * descriptor 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 descriptor will
+   * use to dispatch handlers for any asynchronous operations performed on the
+   * descriptor.
+   */
+  explicit basic_stream_descriptor(boost::asio::io_service& io_service)
+    : basic_descriptor<StreamDescriptorService>(io_service)
+  {
+  }
+
+  /// Construct a basic_stream_descriptor on an existing native descriptor.
+  /**
+   * This constructor creates a stream descriptor object to hold an existing
+   * native descriptor.
+   *
+   * @param io_service The io_service object that the stream descriptor will
+   * use to dispatch handlers for any asynchronous operations performed on the
+   * descriptor.
+   *
+   * @param native_descriptor The new underlying descriptor implementation.
+   *
+   * @throws boost::system::system_error Thrown on failure.
+   */
+  basic_stream_descriptor(boost::asio::io_service& io_service,
+      const native_type& native_descriptor)
+    : basic_descriptor<StreamDescriptorService>(io_service, native_descriptor)
+  {
+  }
+
+  /// Write some data to the descriptor.
+  /**
+   * This function is used to write data to the stream descriptor. 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 descriptor.
+   *
+   * @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
+   * descriptor.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 descriptor.
+  /**
+   * This function is used to write data to the stream descriptor. 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 descriptor.
+   *
+   * @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
+   * descriptor. The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be written to the descriptor.
+   * 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
+   * descriptor.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 descriptor.
+  /**
+   * This function is used to read data from the stream descriptor. 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
+   * descriptor.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 descriptor.
+  /**
+   * This function is used to read data from the stream descriptor. 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
+   * descriptor. 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
+   * descriptor.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 posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
Added: trunk/boost/asio/posix/descriptor_base.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/posix/descriptor_base.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,95 @@
+//
+// descriptor_base.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_POSIX_DESCRIPTOR_BASE_HPP
+#define BOOST_ASIO_POSIX_DESCRIPTOR_BASE_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/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/io_control.hpp>
+#include <boost/asio/detail/socket_option.hpp>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// The descriptor_base class is used as a base for the basic_stream_descriptor
+/// class template so that we have a common place to define the associated
+/// IO control commands.
+class descriptor_base
+{
+public:
+  /// IO control command to set the blocking mode of the descriptor.
+  /**
+   * Implements the FIONBIO IO control command.
+   *
+   * @par Example
+   * @code
+   * boost::asio::posix::stream_descriptor descriptor(io_service); 
+   * ...
+   * boost::asio::descriptor_base::non_blocking_io command(true);
+   * descriptor.io_control(command);
+   * @endcode
+   *
+   * @par Concepts:
+   * IoControlCommand.
+   */
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined non_blocking_io;
+#else
+  typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io;
+#endif
+
+  /// IO control command to get the amount of data that can be read without
+  /// blocking.
+  /**
+   * Implements the FIONREAD IO control command.
+   *
+   * @par Example
+   * @code
+   * boost::asio::posix::stream_descriptor descriptor(io_service); 
+   * ...
+   * boost::asio::descriptor_base::bytes_readable command(true);
+   * descriptor.io_control(command);
+   * std::size_t bytes_readable = command.get();
+   * @endcode
+   *
+   * @par Concepts:
+   * IoControlCommand.
+   */
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined bytes_readable;
+#else
+  typedef boost::asio::detail::io_control::bytes_readable bytes_readable;
+#endif
+
+protected:
+  /// Protected destructor to prevent deletion through this type.
+  ~descriptor_base()
+  {
+  }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP
Added: trunk/boost/asio/posix/stream_descriptor.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/posix/stream_descriptor.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,41 @@
+//
+// stream_descriptor.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_POSIX_STREAM_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_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/posix/basic_stream_descriptor.hpp>
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Typedef for the typical usage of a stream-oriented descriptor.
+typedef basic_stream_descriptor<> stream_descriptor;
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP
Added: trunk/boost/asio/posix/stream_descriptor_service.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/posix/stream_descriptor_service.hpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,202 @@
+//
+// stream_descriptor_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_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
+#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_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/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_descriptor_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#  define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Default service implementation for a stream descriptor.
+class stream_descriptor_service
+#if defined(GENERATING_DOCUMENTATION)
+  : public boost::asio::io_service::service
+#else
+  : public boost::asio::detail::service_base<stream_descriptor_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.
+#if defined(BOOST_ASIO_HAS_EPOLL)
+  typedef detail::reactive_descriptor_service<
+      detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+  typedef detail::reactive_descriptor_service<
+      detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+  typedef detail::reactive_descriptor_service<
+      detail::dev_poll_reactor<false> > service_impl_type;
+#else
+  typedef detail::reactive_descriptor_service<
+      detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+  /// The type of a stream descriptor implementation.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined implementation_type;
+#else
+  typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+  /// The native descriptor type.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined native_type;
+#else
+  typedef service_impl_type::native_type native_type;
+#endif
+
+  /// Construct a new stream descriptor service for the specified io_service.
+  explicit stream_descriptor_service(boost::asio::io_service& io_service)
+    : boost::asio::detail::service_base<stream_descriptor_service>(io_service),
+      service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+  {
+  }
+
+  /// Destroy all user-defined descriptorr objects owned by the service.
+  void shutdown_service()
+  {
+  }
+
+  /// Construct a new stream descriptor implementation.
+  void construct(implementation_type& impl)
+  {
+    service_impl_.construct(impl);
+  }
+
+  /// Destroy a stream descriptor implementation.
+  void destroy(implementation_type& impl)
+  {
+    service_impl_.destroy(impl);
+  }
+
+  /// Assign an existing native descriptor to a stream descriptor.
+  boost::system::error_code assign(implementation_type& impl,
+      const native_type& native_descriptor, boost::system::error_code& ec)
+  {
+    return service_impl_.assign(impl, native_descriptor, ec);
+  }
+
+  /// Determine whether the descriptor is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return service_impl_.is_open(impl);
+  }
+
+  /// Close a stream descriptor implementation.
+  boost::system::error_code close(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    return service_impl_.close(impl, ec);
+  }
+
+  /// Get the native descriptor implementation.
+  native_type native(implementation_type& impl)
+  {
+    return service_impl_.native(impl);
+  }
+
+  /// Cancel all asynchronous operations associated with the descriptor.
+  boost::system::error_code cancel(implementation_type& impl,
+      boost::system::error_code& ec)
+  {
+    return service_impl_.cancel(impl, ec);
+  }
+
+  /// Perform an IO control command on the descriptor.
+  template <typename IoControlCommand>
+  boost::system::error_code io_control(implementation_type& impl,
+      IoControlCommand& command, boost::system::error_code& ec)
+  {
+    return service_impl_.io_control(impl, command, 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 descriptorr)
+  {
+    service_impl_.async_write_some(impl, buffers, descriptorr);
+  }
+
+  /// 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 descriptorr)
+  {
+    service_impl_.async_read_some(impl, buffers, descriptorr);
+  }
+
+private:
+  // The service that provides the platform-specific implementation.
+  service_impl_type& service_impl_;
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
Modified: trunk/libs/asio/test/Jamfile
==============================================================================
--- trunk/libs/asio/test/Jamfile	(original)
+++ trunk/libs/asio/test/Jamfile	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -74,6 +74,11 @@
   [ run local/datagram_protocol.cpp <template>asio_unit_test ]
   [ run local/stream_protocol.cpp <template>asio_unit_test ]
   [ run placeholders.cpp <template>asio_unit_test ]
+  [ run posix/basic_descriptor.cpp <template>asio_unit_test ]
+  [ run posix/basic_stream_descriptor.cpp <template>asio_unit_test ]
+  [ run posix/descriptor_base.cpp <template>asio_unit_test ]
+  [ run posix/stream_descriptor.cpp <template>asio_unit_test ]
+  [ run posix/stream_descriptor_service.cpp <template>asio_unit_test ]
   [ run read.cpp <template>asio_unit_test ]
   [ run read_until.cpp <template>asio_unit_test ]
   [ run socket_acceptor_service.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:16:15 EDT (Mon, 21 Apr 2008)
@@ -126,6 +126,16 @@
   [ link local/stream_protocol.cpp : $(USE_SELECT) : local_stream_protocol_select ]
   [ link placeholders.cpp ]
   [ link placeholders.cpp : $(USE_SELECT) : placeholders_select ]
+  [ link posix/basic_descriptor.cpp : : posix_basic_descriptor ]
+  [ link posix/basic_descriptor.cpp : $(USE_SELECT) : posix_basic_descriptor_select ]
+  [ link posix/basic_stream_descriptor.cpp : : posix_basic_stream_descriptor ]
+  [ link posix/basic_stream_descriptor.cpp : $(USE_SELECT) : posix_basic_stream_descriptor_select ]
+  [ link posix/descriptor_base.cpp : : posix_descriptor_base ]
+  [ link posix/descriptor_base.cpp : $(USE_SELECT) : posix_descriptor_base_select ]
+  [ link posix/stream_descriptor.cpp : : posix_stream_descriptor ]
+  [ link posix/stream_descriptor.cpp : $(USE_SELECT) : posix_stream_descriptor_select ]
+  [ link posix/stream_descriptor_service.cpp : : posix_stream_descriptor_service ]
+  [ link posix/stream_descriptor_service.cpp : $(USE_SELECT) : posix_stream_descriptor_service_select ]
   [ run read.cpp ]
   [ run read.cpp : : : $(USE_SELECT) : read_select ]
   [ run read_until.cpp ]
Added: trunk/libs/asio/test/posix/basic_descriptor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/posix/basic_descriptor.cpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// basic_descriptor.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/posix/basic_descriptor.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("posix/basic_descriptor");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/posix/basic_stream_descriptor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/posix/basic_stream_descriptor.cpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// basic_stream_descriptor.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/posix/basic_stream_descriptor.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("posix/basic_stream_descriptor");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/posix/descriptor_base.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/posix/descriptor_base.cpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// descriptor_base.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/posix/descriptor_base.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("posix/descriptor_base");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}
Added: trunk/libs/asio/test/posix/stream_descriptor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/posix/stream_descriptor.cpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,127 @@
+//
+// stream_descriptor.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/posix/stream_descriptor.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// posix_stream_descriptor_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// posix::stream_descriptor compile and link correctly. Runtime failures are
+// ignored.
+
+namespace posix_stream_descriptor_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_POSIX_STREAM_DESCRIPTOR)
+  using namespace boost::asio;
+  namespace posix = boost::asio::posix;
+
+  try
+  {
+    io_service ios;
+    char mutable_char_buffer[128] = "";
+    const char const_char_buffer[128] = "";
+    posix::descriptor_base::bytes_readable io_control_command;
+    boost::system::error_code ec;
+
+    // basic_stream_descriptor constructors.
+
+    posix::stream_descriptor descriptor1(ios);
+    int native_descriptor1 = -1;
+    posix::stream_descriptor descriptor2(ios, native_descriptor1);
+
+    // basic_io_object functions.
+
+    io_service& ios_ref = descriptor1.io_service();
+    (void)ios_ref;
+
+    // basic_descriptor functions.
+
+    posix::stream_descriptor::lowest_layer_type& lowest_layer
+      = descriptor1.lowest_layer();
+    (void)lowest_layer;
+
+    int native_descriptor2 = -1;
+    descriptor1.assign(native_descriptor2);
+
+    bool is_open = descriptor1.is_open();
+    (void)is_open;
+
+    descriptor1.close();
+    descriptor1.close(ec);
+
+    posix::stream_descriptor::native_type native_descriptor3
+      = descriptor1.native();
+    (void)native_descriptor3;
+
+    descriptor1.cancel();
+    descriptor1.cancel(ec);
+
+    descriptor1.io_control(io_control_command);
+    descriptor1.io_control(io_control_command, ec);
+
+    // basic_stream_descriptor functions.
+
+    descriptor1.write_some(buffer(mutable_char_buffer));
+    descriptor1.write_some(buffer(const_char_buffer));
+    descriptor1.write_some(null_buffers());
+    descriptor1.write_some(buffer(mutable_char_buffer), ec);
+    descriptor1.write_some(buffer(const_char_buffer), ec);
+    descriptor1.write_some(null_buffers(), ec);
+
+    descriptor1.async_write_some(buffer(mutable_char_buffer),
+        write_some_handler);
+    descriptor1.async_write_some(buffer(const_char_buffer),
+        write_some_handler);
+    descriptor1.async_write_some(null_buffers(),
+        write_some_handler);
+
+    descriptor1.read_some(buffer(mutable_char_buffer));
+    descriptor1.read_some(buffer(mutable_char_buffer), ec);
+    descriptor1.read_some(null_buffers(), ec);
+
+    descriptor1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+    descriptor1.async_read_some(null_buffers(), read_some_handler);
+  }
+  catch (std::exception&)
+  {
+  }
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+}
+
+} // namespace posix_stream_descriptor_compile
+
+//------------------------------------------------------------------------------
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+  test_suite* test = BOOST_TEST_SUITE("posix/stream_descriptor");
+  test->add(BOOST_TEST_CASE(&posix_stream_descriptor_compile::test));
+  return test;
+}
Added: trunk/libs/asio/test/posix/stream_descriptor_service.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/posix/stream_descriptor_service.cpp	2008-04-21 01:16:15 EDT (Mon, 21 Apr 2008)
@@ -0,0 +1,27 @@
+//
+// stream_descriptor_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/posix/stream_descriptor_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("posix/stream_descriptor_service");
+  test->add(BOOST_TEST_CASE(&null_test));
+  return test;
+}