$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r49221 - in branches/release: . boost/asio boost/asio/detail boost/asio/ip libs/asio/example/local
From: chris_at_[hidden]
Date: 2008-10-09 16:43:28
Author: chris_kohlhoff
Date: 2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
New Revision: 49221
URL: http://svn.boost.org/trac/boost/changeset/49221
Log:
Merge from trunk.
........
  r49155 | nmusatti | 2008-10-07 08:46:14 +1100 (Tue, 07 Oct 2008) | 1 line
  
  Patch from  Ticket #2372
........
  r49195 | chris_kohlhoff | 2008-10-09 17:22:58 +1100 (Thu, 09 Oct 2008) | 2 lines
  
  Add missing bounds checks as specified in TR2 proposal.
........
  r49197 | chris_kohlhoff | 2008-10-09 17:28:39 +1100 (Thu, 09 Oct 2008) | 2 lines
  
  Merge codegear changes from non-boost version of asio.
........
  r49198 | chris_kohlhoff | 2008-10-09 17:30:16 +1100 (Thu, 09 Oct 2008) | 4 lines
  
  Ensure the streambuf's egptr() is kept in sync the pptr(). Use std::memmove
  rather than std::rotate to minimise data copying. Avoid unnecessary resizes
  of the underlying vector.
........
  r49199 | chris_kohlhoff | 2008-10-09 17:31:01 +1100 (Thu, 09 Oct 2008) | 3 lines
  
  Fix basic_socket_streambuf to work with Protocol objects that don't
  provide a resolver.
........
  r49200 | chris_kohlhoff | 2008-10-09 17:32:00 +1100 (Thu, 09 Oct 2008) | 2 lines
  
  Add example showing use of local::stream_protocol::iostream.
........
  r49201 | chris_kohlhoff | 2008-10-09 17:33:34 +1100 (Thu, 09 Oct 2008) | 4 lines
  
  Only use TerminateThread when explicitly requested by the user by calling
  asio::detail::thread::set_terminate_threads(true). This fixes a memory leak
  that may occur with internally created threads.
........
  r49202 | chris_kohlhoff | 2008-10-09 17:34:48 +1100 (Thu, 09 Oct 2008) | 3 lines
  
  Make the service_registry's usage of typeid work when the default gcc
  linker visibility is set to hidden.
........
  r49203 | chris_kohlhoff | 2008-10-09 17:39:05 +1100 (Thu, 09 Oct 2008) | 2 lines
  
  Reduce memory usage by doing lazy initialisation of the io_service's reactor.
........
Added:
   branches/release/libs/asio/example/local/iostream_client.cpp
      - copied unchanged from r49203, /trunk/libs/asio/example/local/iostream_client.cpp
Properties modified: 
   branches/release/   (props changed)
Text files modified: 
   branches/release/boost/asio/basic_socket_streambuf.hpp             |     3                                         
   branches/release/boost/asio/basic_streambuf.hpp                    |    13 ++--                                    
   branches/release/boost/asio/detail/deadline_timer_service.hpp      |     1                                         
   branches/release/boost/asio/detail/dev_poll_reactor.hpp            |    11 +++                                     
   branches/release/boost/asio/detail/epoll_reactor.hpp               |    10 +++                                     
   branches/release/boost/asio/detail/kqueue_reactor.hpp              |    10 +++                                     
   branches/release/boost/asio/detail/null_thread.hpp                 |     5 -                                       
   branches/release/boost/asio/detail/posix_thread.hpp                |     5 -                                       
   branches/release/boost/asio/detail/reactive_descriptor_service.hpp |     1                                         
   branches/release/boost/asio/detail/reactive_socket_service.hpp     |     1                                         
   branches/release/boost/asio/detail/select_reactor.hpp              |    10 +++                                     
   branches/release/boost/asio/detail/service_registry.hpp            |    20 ++++++                                  
   branches/release/boost/asio/detail/task_io_service.hpp             |    31 +++++++---                              
   branches/release/boost/asio/detail/task_io_service_2lock.hpp       |    31 +++++++---                              
   branches/release/boost/asio/detail/win_iocp_io_service.hpp         |     5 +                                       
   branches/release/boost/asio/detail/win_thread.hpp                  |   117 +++++++++++++++++++++++++-------------- 
   branches/release/boost/asio/detail/wince_thread.hpp                |     5 -                                       
   branches/release/boost/asio/ip/address_v4.hpp                      |    19 ++++++                                  
   branches/release/boost/asio/ip/address_v6.hpp                      |    17 +++++                                   
   branches/release/boost/asio/read_until.hpp                         |    16 +++++                                   
   branches/release/libs/asio/example/local/Jamfile                   |    12 ++++                                    
   branches/release/libs/asio/example/local/Jamfile.v2                |    15 +++++                                   
   22 files changed, 274 insertions(+), 84 deletions(-)
Modified: branches/release/boost/asio/basic_socket_streambuf.hpp
==============================================================================
--- branches/release/boost/asio/basic_socket_streambuf.hpp	(original)
+++ branches/release/boost/asio/basic_socket_streambuf.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -248,7 +248,8 @@
       setp(put_buffer_.begin(), put_buffer_.end());
   }
 
-  void resolve_and_connect(const typename Protocol::resolver_query& query,
+  template <typename ResolverQuery>
+  void resolve_and_connect(const ResolverQuery& query,
       boost::system::error_code& ec)
   {
     typedef typename Protocol::resolver resolver_type;
Modified: branches/release/boost/asio/basic_streambuf.hpp
==============================================================================
--- branches/release/boost/asio/basic_streambuf.hpp	(original)
+++ branches/release/boost/asio/basic_streambuf.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -19,6 +19,7 @@
 
 #include <boost/asio/detail/push_options.hpp>
 #include <algorithm>
+#include <cstring>
 #include <limits>
 #include <memory>
 #include <stdexcept>
@@ -96,6 +97,7 @@
     if (pptr() + n > epptr())
       n = epptr() - pptr();
     pbump(static_cast<int>(n));
+    setg(eback(), gptr(), pptr());
   }
 
   /// Move the start of the get area by the specified number of characters.
@@ -151,7 +153,6 @@
   {
     // Get current stream positions as offsets.
     std::size_t gnext = gptr() - &buffer_[0];
-    std::size_t gend = egptr() - &buffer_[0];
     std::size_t pnext = pptr() - &buffer_[0];
     std::size_t pend = epptr() - &buffer_[0];
 
@@ -164,9 +165,8 @@
     // Shift existing contents of get area to start of buffer.
     if (gnext > 0)
     {
-      std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
-      gend -= gnext;
       pnext -= gnext;
+      std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext);
     }
 
     // Ensure buffer is large enough to hold at least the specified size.
@@ -174,7 +174,8 @@
     {
       if (n <= max_size_ && pnext <= max_size_ - n)
       {
-        buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
+        pend = pnext + n;
+        buffer_.resize((std::max<std::size_t>)(pend, 1));
       }
       else
       {
@@ -183,8 +184,8 @@
     }
 
     // Update stream positions.
-    setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
-    setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
+    setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext);
+    setp(&buffer_[0] + pnext, &buffer_[0] + pend);
   }
 
 private:
Modified: branches/release/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/deadline_timer_service.hpp	(original)
+++ branches/release/boost/asio/detail/deadline_timer_service.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -64,6 +64,7 @@
         deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
       scheduler_(boost::asio::use_service<Timer_Scheduler>(io_service))
   {
+    scheduler_.init_task();
     scheduler_.add_timer_queue(timer_queue_);
   }
 
Modified: branches/release/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/dev_poll_reactor.hpp	(original)
+++ branches/release/boost/asio/detail/dev_poll_reactor.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -123,6 +123,17 @@
     timer_queues_.clear();
   } 
 
+  // Initialise the task, but only if the reactor is not in its own thread.
+  void init_task()
+  {
+    if (!Own_Thread)
+    {
+      typedef task_io_service<dev_poll_reactor<Own_Thread> >
+        task_io_service_type;
+      use_service<task_io_service_type>(this->get_io_service()).init_task();
+    }
+  }
+
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
   int register_descriptor(socket_type, per_descriptor_data&)
Modified: branches/release/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/epoll_reactor.hpp	(original)
+++ branches/release/boost/asio/detail/epoll_reactor.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -124,6 +124,16 @@
     timer_queues_.clear();
   }
 
+  // Initialise the task, but only if the reactor is not in its own thread.
+  void init_task()
+  {
+    if (!Own_Thread)
+    {
+      typedef task_io_service<epoll_reactor<Own_Thread> > task_io_service_type;
+      use_service<task_io_service_type>(this->get_io_service()).init_task();
+    }
+  }
+
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
   int register_descriptor(socket_type descriptor,
Modified: branches/release/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/kqueue_reactor.hpp	(original)
+++ branches/release/boost/asio/detail/kqueue_reactor.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -132,6 +132,16 @@
     timer_queues_.clear();
   }
 
+  // Initialise the task, but only if the reactor is not in its own thread.
+  void init_task()
+  {
+    if (!Own_Thread)
+    {
+      typedef task_io_service<kqueue_reactor<Own_Thread> > task_io_service_type;
+      use_service<task_io_service_type>(this->get_io_service()).init_task();
+    }
+  }
+
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
   int register_descriptor(socket_type, per_descriptor_data& descriptor_data)
Modified: branches/release/boost/asio/detail/null_thread.hpp
==============================================================================
--- branches/release/boost/asio/detail/null_thread.hpp	(original)
+++ branches/release/boost/asio/detail/null_thread.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -39,12 +39,9 @@
   : private noncopyable
 {
 public:
-  // The purpose of the thread.
-  enum purpose { internal, external };
-
   // Constructor.
   template <typename Function>
-  null_thread(Function f, purpose = internal)
+  null_thread(Function f)
   {
     boost::system::system_error e(
         boost::asio::error::operation_not_supported, "thread");
Modified: branches/release/boost/asio/detail/posix_thread.hpp
==============================================================================
--- branches/release/boost/asio/detail/posix_thread.hpp	(original)
+++ branches/release/boost/asio/detail/posix_thread.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -43,12 +43,9 @@
   : private noncopyable
 {
 public:
-  // The purpose of the thread.
-  enum purpose { internal, external };
-
   // Constructor.
   template <typename Function>
-  posix_thread(Function f, purpose = internal)
+  posix_thread(Function f)
     : joined_(false)
   {
     std::auto_ptr<func_base> arg(new func<Function>(f));
Modified: branches/release/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactive_descriptor_service.hpp	(original)
+++ branches/release/boost/asio/detail/reactive_descriptor_service.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -82,6 +82,7 @@
         reactive_descriptor_service<Reactor> >(io_service),
       reactor_(boost::asio::use_service<Reactor>(io_service))
   {
+    reactor_.init_task();
   }
 
   // Destroy all user-defined handler objects owned by the service.
Modified: branches/release/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/reactive_socket_service.hpp	(original)
+++ branches/release/boost/asio/detail/reactive_socket_service.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -110,6 +110,7 @@
         reactive_socket_service<Protocol, Reactor> >(io_service),
       reactor_(boost::asio::use_service<Reactor>(io_service))
   {
+    reactor_.init_task();
   }
 
   // Destroy all user-defined handler objects owned by the service.
Modified: branches/release/boost/asio/detail/select_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/select_reactor.hpp	(original)
+++ branches/release/boost/asio/detail/select_reactor.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -111,6 +111,16 @@
     timer_queues_.clear();
   }
 
+  // Initialise the task, but only if the reactor is not in its own thread.
+  void init_task()
+  {
+    if (!Own_Thread)
+    {
+      typedef task_io_service<select_reactor<Own_Thread> > task_io_service_type;
+      use_service<task_io_service_type>(this->get_io_service()).init_task();
+    }
+  }
+
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
   int register_descriptor(socket_type, per_descriptor_data&)
Modified: branches/release/boost/asio/detail/service_registry.hpp
==============================================================================
--- branches/release/boost/asio/detail/service_registry.hpp	(original)
+++ branches/release/boost/asio/detail/service_registry.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -37,6 +37,21 @@
 namespace asio {
 namespace detail {
 
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#  pragma GCC visibility push (default)
+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+
+template <typename T>
+class typeid_wrapper {};
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#  pragma GCC visibility pop
+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+
 class service_registry
   : private noncopyable
 {
@@ -169,7 +184,7 @@
   void init_service_id(boost::asio::io_service::service& service,
       const boost::asio::detail::service_id<Service>& /*id*/)
   {
-    service.type_info_ = &typeid(Service);
+    service.type_info_ = &typeid(typeid_wrapper<Service>);
     service.id_ = 0;
   }
 #endif // !defined(BOOST_ASIO_NO_TYPEID)
@@ -189,7 +204,8 @@
       const boost::asio::io_service::service& service,
       const boost::asio::detail::service_id<Service>& /*id*/)
   {
-    return service.type_info_ != 0 && *service.type_info_ == typeid(Service);
+    return service.type_info_ != 0
+      && *service.type_info_ == typeid(typeid_wrapper<Service>);
   }
 #endif // !defined(BOOST_ASIO_NO_TYPEID)
 
Modified: branches/release/boost/asio/detail/task_io_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/task_io_service.hpp	(original)
+++ branches/release/boost/asio/detail/task_io_service.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -44,14 +44,13 @@
   task_io_service(boost::asio::io_service& io_service)
     : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
       mutex_(),
-      task_(use_service<Task>(io_service)),
+      task_(0),
       task_interrupted_(true),
       outstanding_work_(0),
       stopped_(false),
       shutdown_(false),
       first_idle_thread_(0)
   {
-    handler_queue_.push(&task_handler_);
   }
 
   void init(size_t /*concurrency_hint*/)
@@ -74,8 +73,20 @@
         h->destroy();
     }
 
-    // Reset handler queue to initial state.
-    handler_queue_.push(&task_handler_);
+    // Reset to initial state.
+    task_ = 0;
+  }
+
+  // Initialise the task, if required.
+  void init_task()
+  {
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    if (!shutdown_ && !task_)
+    {
+      task_ = &use_service<Task>(this->get_io_service());
+      handler_queue_.push(&task_handler_);
+      interrupt_one_idle_thread(lock);
+    }
   }
 
   // Run the event loop until interrupted or no more work.
@@ -194,10 +205,10 @@
     // Wake up a thread to execute the handler.
     if (!interrupt_one_idle_thread(lock))
     {
-      if (!task_interrupted_)
+      if (!task_interrupted_ && task_)
       {
         task_interrupted_ = true;
-        task_.interrupt();
+        task_->interrupt();
       }
     }
   }
@@ -246,7 +257,7 @@
           // Run the task. May throw an exception. Only block if the handler
           // queue is empty and we have an idle_thread_info object, otherwise
           // we want to return as soon as possible.
-          task_.run(!more_handlers && !polling);
+          task_->run(!more_handlers && !polling);
         }
         else
         {
@@ -285,10 +296,10 @@
   {
     stopped_ = true;
     interrupt_all_idle_threads(lock);
-    if (!task_interrupted_)
+    if (!task_interrupted_ && task_)
     {
       task_interrupted_ = true;
-      task_.interrupt();
+      task_->interrupt();
     }
   }
 
@@ -376,7 +387,7 @@
   boost::asio::detail::mutex mutex_;
 
   // The task to be run by this service.
-  Task& task_;
+  Task* task_;
 
   // Handler object to represent the position of the task in the queue.
   class task_handler
Modified: branches/release/boost/asio/detail/task_io_service_2lock.hpp
==============================================================================
--- branches/release/boost/asio/detail/task_io_service_2lock.hpp	(original)
+++ branches/release/boost/asio/detail/task_io_service_2lock.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -50,7 +50,7 @@
     : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
       front_mutex_(),
       back_mutex_(),
-      task_(use_service<Task>(io_service)),
+      task_(&use_service<Task>(io_service)),
       outstanding_work_(0),
       front_stopped_(false),
       back_stopped_(false),
@@ -58,7 +58,6 @@
       back_first_idle_thread_(0),
       back_task_thread_(0)
   {
-    handler_queue_.push(&task_handler_);
   }
 
   void init(size_t /*concurrency_hint*/)
@@ -77,8 +76,20 @@
       if (h != &task_handler_)
         h->destroy();
 
-    // Reset handler queue to initial state.
-    handler_queue_.push(&task_handler_);
+    // Reset to initial state.
+    task_ = 0;
+  }
+
+  // Initialise the task, if required.
+  void init_task()
+  {
+    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+    if (!back_shutdown_ && !task_)
+    {
+      task_ = &use_service<Task>(this->get_io_service());
+      handler_queue_.push(&task_handler_);
+      interrupt_one_idle_thread(back_lock);
+    }
   }
 
   // Run the event loop until interrupted or no more work.
@@ -287,7 +298,7 @@
           // queue is empty and we're not polling, otherwise we want to return
           // as soon as possible.
           task_has_run = true;
-          task_.run(!more_handlers && !polling);
+          task_->run(!more_handlers && !polling);
         }
         else
         {
@@ -342,10 +353,10 @@
       idle_thread->next = 0;
       idle_thread->wakeup_event.signal(back_lock);
     }
-    else if (back_task_thread_)
+    else if (back_task_thread_ && task_)
     {
       back_task_thread_ = 0;
-      task_.interrupt();
+      task_->interrupt();
     }
   }
 
@@ -361,10 +372,10 @@
       idle_thread->wakeup_event.signal(back_lock);
     }
 
-    if (back_task_thread_)
+    if (back_task_thread_ && task_)
     {
       back_task_thread_ = 0;
-      task_.interrupt();
+      task_->interrupt();
     }
   }
 
@@ -415,7 +426,7 @@
   boost::asio::detail::mutex back_mutex_;
 
   // The task to be run by this service.
-  Task& task_;
+  Task* task_;
 
   // Handler object to represent the position of the task in the queue.
   class task_handler
Modified: branches/release/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_io_service.hpp	(original)
+++ branches/release/boost/asio/detail/win_iocp_io_service.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -149,6 +149,11 @@
     timer_queues_.clear();
   }
 
+  // Initialise the task. Nothing to do here.
+  void init_task()
+  {
+  }
+
   // Register a handle with the IO completion port.
   boost::system::error_code register_handle(
       HANDLE handle, boost::system::error_code& ec)
Modified: branches/release/boost/asio/detail/win_thread.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_thread.hpp	(original)
+++ branches/release/boost/asio/detail/win_thread.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -40,50 +40,67 @@
 
 unsigned int __stdcall win_thread_function(void* arg);
 
-class win_thread
-  : private noncopyable
+#if (WINVER < 0x0500)
+void __stdcall apc_function(ULONG data);
+#else
+void __stdcall apc_function(ULONG_PTR data);
+#endif
+
+template <typename T>
+class win_thread_base
 {
 public:
-  // The purpose of the thread.
-  enum purpose { internal, external };
+  static bool terminate_threads()
+  {
+    return ::InterlockedExchangeAdd(&terminate_threads_, 0) != 0;
+  }
+
+  static void set_terminate_threads(bool b)
+  {
+    ::InterlockedExchange(&terminate_threads_, b ? 1 : 0);
+  }
+
+private:
+  static long terminate_threads_;
+};
 
+template <typename T>
+long win_thread_base<T>::terminate_threads_ = 0;
+
+class win_thread
+  : private noncopyable,
+    public win_thread_base<win_thread>
+{
+public:
   // Constructor.
   template <typename Function>
-  win_thread(Function f, purpose p = internal)
+  win_thread(Function f)
     : exit_event_(0)
   {
     std::auto_ptr<func_base> arg(new func<Function>(f));
 
     ::HANDLE entry_event = 0;
-    if (p == internal)
+    arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
+    if (!entry_event)
     {
-      arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
-      if (!entry_event)
-      {
-        DWORD last_error = ::GetLastError();
-        boost::system::system_error e(
-            boost::system::error_code(last_error,
-              boost::asio::error::get_system_category()),
-            "thread.entry_event");
-        boost::throw_exception(e);
-      }
-
-      arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
-      if (!exit_event_)
-      {
-        DWORD last_error = ::GetLastError();
-        ::CloseHandle(entry_event);
-        boost::system::system_error e(
-            boost::system::error_code(last_error,
-              boost::asio::error::get_system_category()),
-            "thread.exit_event");
-        boost::throw_exception(e);
-      }
+      DWORD last_error = ::GetLastError();
+      boost::system::system_error e(
+          boost::system::error_code(last_error,
+            boost::asio::error::get_system_category()),
+          "thread.entry_event");
+      boost::throw_exception(e);
     }
-    else
+
+    arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
+    if (!exit_event_)
     {
-      arg->entry_event_ = 0;
-      arg->exit_event_ = 0;
+      DWORD last_error = ::GetLastError();
+      ::CloseHandle(entry_event);
+      boost::system::system_error e(
+          boost::system::error_code(last_error,
+            boost::asio::error::get_system_category()),
+          "thread.exit_event");
+      boost::throw_exception(e);
     }
 
     unsigned int thread_id = 0;
@@ -123,14 +140,15 @@
   // Wait for the thread to exit.
   void join()
   {
-    if (exit_event_)
+    ::WaitForSingleObject(exit_event_, INFINITE);
+    ::CloseHandle(exit_event_);
+    if (terminate_threads())
     {
-      ::WaitForSingleObject(exit_event_, INFINITE);
-      ::CloseHandle(exit_event_);
       ::TerminateThread(thread_, 0);
     }
     else
     {
+      ::QueueUserAPC(apc_function, thread_, 0);
       ::WaitForSingleObject(thread_, INFINITE);
     }
   }
@@ -138,6 +156,12 @@
 private:
   friend unsigned int __stdcall win_thread_function(void* arg);
 
+#if (WINVER < 0x0500)
+  friend void __stdcall apc_function(ULONG);
+#else
+  friend void __stdcall apc_function(ULONG_PTR);
+#endif
+
   class func_base
   {
   public:
@@ -175,21 +199,30 @@
   std::auto_ptr<win_thread::func_base> func(
       static_cast<win_thread::func_base*>(arg));
 
-  if (func->entry_event_)
-    ::SetEvent(func->entry_event_);
+  ::SetEvent(func->entry_event_);
 
   func->run();
 
-  if (HANDLE exit_event = func->exit_event_)
-  {
-    func.reset();
-    ::SetEvent(exit_event);
-    ::Sleep(INFINITE);
-  }
+  // Signal that the thread has finished its work, but rather than returning go
+  // to sleep to put the thread into a well known state. If the thread is being
+  // joined during global object destruction then it may be killed using
+  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
+  // call will be interrupted using QueueUserAPC and the thread will shut down
+  // cleanly.
+  HANDLE exit_event = func->exit_event_;
+  func.reset();
+  ::SetEvent(exit_event);
+  ::SleepEx(INFINITE, TRUE);
 
   return 0;
 }
 
+#if (WINVER < 0x0500)
+inline void __stdcall apc_function(ULONG) {}
+#else
+inline void __stdcall apc_function(ULONG_PTR) {}
+#endif
+
 } // namespace detail
 } // namespace asio
 } // namespace boost
Modified: branches/release/boost/asio/detail/wince_thread.hpp
==============================================================================
--- branches/release/boost/asio/detail/wince_thread.hpp	(original)
+++ branches/release/boost/asio/detail/wince_thread.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -43,12 +43,9 @@
   : private noncopyable
 {
 public:
-  // The purpose of the thread.
-  enum purpose { internal, external };
-
   // Constructor.
   template <typename Function>
-  wince_thread(Function f, purpose = internal)
+  wince_thread(Function f)
   {
     std::auto_ptr<func_base> arg(new func<Function>(f));
     DWORD thread_id = 0;
Modified: branches/release/boost/asio/ip/address_v4.hpp
==============================================================================
--- branches/release/boost/asio/ip/address_v4.hpp	(original)
+++ branches/release/boost/asio/ip/address_v4.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -18,7 +18,9 @@
 #include <boost/asio/detail/push_options.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
+#include <climits>
 #include <string>
+#include <stdexcept>
 #include <boost/array.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/asio/detail/pop_options.hpp>
@@ -56,6 +58,15 @@
   /// Construct an address from raw bytes.
   explicit address_v4(const bytes_type& bytes)
   {
+#if UCHAR_MAX > 0xFF
+    if (bytes[0] > 0xFF || bytes[1] > 0xFF
+        || bytes[2] > 0xFF || bytes[3] > 0xFF)
+    {
+      std::out_of_range ex("address_v4 from bytes_type");
+      boost::throw_exception(ex);
+    }
+#endif // UCHAR_MAX > 0xFF
+
     using namespace std; // For memcpy.
     memcpy(&addr_.s_addr, bytes.elems, 4);
   }
@@ -63,6 +74,14 @@
   /// Construct an address from a unsigned long in host byte order.
   explicit address_v4(unsigned long addr)
   {
+#if ULONG_MAX > 0xFFFFFFFF
+    if (addr > 0xFFFFFFFF)
+    {
+      std::out_of_range ex("address_v4 from unsigned long");
+      boost::throw_exception(ex);
+    }
+#endif // ULONG_MAX > 0xFFFFFFFF
+
     addr_.s_addr = boost::asio::detail::socket_ops::host_to_network_long(addr);
   }
 
Modified: branches/release/boost/asio/ip/address_v6.hpp
==============================================================================
--- branches/release/boost/asio/ip/address_v6.hpp	(original)
+++ branches/release/boost/asio/ip/address_v6.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -63,6 +63,17 @@
   explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
     : scope_id_(scope_id)
   {
+#if UCHAR_MAX > 0xFF
+    for (std::size_t i = 0; i < bytes.size(); ++i)
+    {
+      if (bytes[i] > 0xFF)
+      {
+        std::out_of_range ex("address_v6 from bytes_type");
+        boost::throw_exception(ex);
+      }
+    }
+#endif // UCHAR_MAX > 0xFF
+
     using namespace std; // For memcpy.
     memcpy(addr_.s6_addr, bytes.elems, 16);
   }
@@ -166,7 +177,11 @@
   address_v4 to_v4() const
   {
     if (!is_v4_mapped() && !is_v4_compatible())
-      throw std::bad_cast();
+    {
+      std::bad_cast ex;
+      boost::throw_exception(ex);
+    }
+
     address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
       addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
     return address_v4(v4_bytes);
Modified: branches/release/boost/asio/read_until.hpp
==============================================================================
--- branches/release/boost/asio/read_until.hpp	(original)
+++ branches/release/boost/asio/read_until.hpp	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -24,6 +24,7 @@
 #include <boost/type_traits/is_function.hpp>
 #include <boost/type_traits/remove_pointer.hpp>
 #include <boost/utility/enable_if.hpp>
+#include <boost/detail/workaround.hpp>
 #include <string>
 #include <boost/asio/detail/pop_options.hpp>
 
@@ -35,6 +36,20 @@
 
 namespace detail
 {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
+  template <typename T>
+  struct has_result_type
+  {
+    template <typename U> struct inner
+    {
+        struct big { char a[100]; };
+        static big helper(U, ...);
+        static char helper(U, typename U::result_type* = 0);
+    };
+    static const T& ref();
+    enum { value = (sizeof((inner<const T&>::helper)((ref)())) == 1) };
+  };
+#else // BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
   template <typename T>
   struct has_result_type
   {
@@ -44,6 +59,7 @@
     static const T& ref();
     enum { value = (sizeof((helper)((ref)())) == 1) };
   };
+#endif // BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
 } // namespace detail
 
 /// Type trait used to determine whether a type can be used as a match condition
Modified: branches/release/libs/asio/example/local/Jamfile
==============================================================================
--- branches/release/libs/asio/example/local/Jamfile	(original)
+++ branches/release/libs/asio/example/local/Jamfile	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -33,6 +33,18 @@
     $(SOCKET_LIBS)
   ;
 
+exe iostream_client
+  : <lib>@boost/libs/system/build/boost_system
+    iostream_client.cpp
+  : <include>$(BOOST_ROOT)
+    <include>../../../..
+    <define>BOOST_ALL_NO_LIB=1
+    <threading>multi
+    <mingw><*><find-library>ws2_32
+    <mingw><*><find-library>mswsock
+    $(SOCKET_LIBS)
+  ;
+
 exe stream_client
   : <lib>@boost/libs/system/build/boost_system
     stream_client.cpp
Modified: branches/release/libs/asio/example/local/Jamfile.v2
==============================================================================
--- branches/release/libs/asio/example/local/Jamfile.v2	(original)
+++ branches/release/libs/asio/example/local/Jamfile.v2	2008-10-09 16:43:26 EDT (Thu, 09 Oct 2008)
@@ -38,6 +38,21 @@
     <os>HPUX:<library>ipv6
   ;
 
+exe iostream_client
+  : iostream_client.cpp
+    /boost/system//boost_system
+  : <define>BOOST_ALL_NO_LIB=1
+    <threading>multi
+    <os>SOLARIS:<library>socket
+    <os>SOLARIS:<library>nsl
+    <os>NT:<define>_WIN32_WINNT=0x0501
+    <os>NT,<toolset>gcc:<library>ws2_32
+    <os>NT,<toolset>gcc:<library>mswsock
+    <os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+    <os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+    <os>HPUX:<library>ipv6
+  ;
+
 exe stream_client
   : stream_client.cpp
     /boost/system//boost_system