Boost logo

Boost-Commit :

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


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