|
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