summaryrefslogtreecommitdiff
path: root/boost/asio
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-08-26 08:15:55 -0400
committerAnas Nashif <anas.nashif@intel.com>2013-08-26 08:15:55 -0400
commitbb4dd8289b351fae6b55e303f189127a394a1edd (patch)
tree77c9c35a31b1459dd7988c2448e797d142530c41 /boost/asio
parent1a78a62555be32868418fe52f8e330c9d0f95d5a (diff)
downloadboost-bb4dd8289b351fae6b55e303f189127a394a1edd.tar.gz
boost-bb4dd8289b351fae6b55e303f189127a394a1edd.tar.bz2
boost-bb4dd8289b351fae6b55e303f189127a394a1edd.zip
Imported Upstream version 1.51.0upstream/1.51.0
Diffstat (limited to 'boost/asio')
-rw-r--r--boost/asio/basic_socket_iostream.hpp6
-rw-r--r--boost/asio/buffered_write_stream.hpp2
-rw-r--r--boost/asio/buffers_iterator.hpp4
-rw-r--r--boost/asio/detail/atomic_count.hpp3
-rw-r--r--boost/asio/detail/config.hpp33
-rw-r--r--boost/asio/detail/epoll_reactor.hpp2
-rw-r--r--boost/asio/detail/fenced_block.hpp6
-rw-r--r--boost/asio/detail/gcc_x86_fenced_block.hpp21
-rw-r--r--boost/asio/detail/impl/epoll_reactor.ipp50
-rw-r--r--boost/asio/detail/impl/socket_ops.ipp1
-rw-r--r--boost/asio/detail/impl/strand_service.hpp5
-rw-r--r--boost/asio/detail/impl/strand_service.ipp2
-rw-r--r--boost/asio/detail/impl/task_io_service.hpp2
-rw-r--r--boost/asio/detail/impl/task_io_service.ipp176
-rw-r--r--boost/asio/detail/keyword_tss_ptr.hpp72
-rw-r--r--boost/asio/detail/strand_service.hpp3
-rw-r--r--boost/asio/detail/task_io_service.hpp28
-rw-r--r--boost/asio/detail/tss_ptr.hpp6
-rw-r--r--boost/asio/detail/win_iocp_io_service.hpp16
-rw-r--r--boost/asio/ssl/detail/impl/engine.ipp10
-rw-r--r--boost/asio/ssl/detail/impl/openssl_init.ipp2
-rw-r--r--boost/asio/ssl/detail/openssl_types.hpp4
-rw-r--r--boost/asio/strand.hpp1
-rw-r--r--boost/asio/version.hpp2
-rw-r--r--boost/asio/windows/basic_object_handle.hpp6
25 files changed, 352 insertions, 111 deletions
diff --git a/boost/asio/basic_socket_iostream.hpp b/boost/asio/basic_socket_iostream.hpp
index 93d1fcd17c..6fae0854b2 100644
--- a/boost/asio/basic_socket_iostream.hpp
+++ b/boost/asio/basic_socket_iostream.hpp
@@ -53,7 +53,7 @@
basic_socket_streambuf<Protocol, StreamSocketService, \
Time, TimeTraits, TimerService> >::member) \
{ \
- tie(this); \
+ this->setf(std::ios_base::unitbuf); \
if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
this->setstate(std::ios_base::failbit); \
} \
@@ -112,7 +112,7 @@ public:
basic_socket_streambuf<Protocol, StreamSocketService,
Time, TimeTraits, TimerService> >::member)
{
- tie(this);
+ this->setf(std::ios_base::unitbuf);
}
#if defined(GENERATING_DOCUMENTATION)
@@ -131,7 +131,7 @@ public:
basic_socket_streambuf<Protocol, StreamSocketService,
Time, TimeTraits, TimerService> >::member)
{
- tie(this);
+ this->setf(std::ios_base::unitbuf);
if (rdbuf()->connect(x...) == 0)
this->setstate(std::ios_base::failbit);
}
diff --git a/boost/asio/buffered_write_stream.hpp b/boost/asio/buffered_write_stream.hpp
index 9159c237f6..11cb872558 100644
--- a/boost/asio/buffered_write_stream.hpp
+++ b/boost/asio/buffered_write_stream.hpp
@@ -232,7 +232,7 @@ public:
? bytes_avail : space_avail;
storage_.resize(orig_size + length);
std::size_t bytes_copied = boost::asio::buffer_copy(
- storage_.data(), buffers_, length);
+ storage_.data() + orig_size, buffers_, length);
io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
}
diff --git a/boost/asio/buffers_iterator.hpp b/boost/asio/buffers_iterator.hpp
index 66b8cf6042..c11e1469d6 100644
--- a/boost/asio/buffers_iterator.hpp
+++ b/boost/asio/buffers_iterator.hpp
@@ -128,7 +128,7 @@ public:
/// Construct an iterator representing the beginning of the buffers' data.
static buffers_iterator begin(const BufferSequence& buffers)
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
- __attribute__ ((noinline))
+ __attribute__ ((__noinline__))
#endif
{
buffers_iterator new_iter;
@@ -148,7 +148,7 @@ public:
/// Construct an iterator representing the end of the buffers' data.
static buffers_iterator end(const BufferSequence& buffers)
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
- __attribute__ ((noinline))
+ __attribute__ ((__noinline__))
#endif
{
buffers_iterator new_iter;
diff --git a/boost/asio/detail/atomic_count.hpp b/boost/asio/detail/atomic_count.hpp
index 9324fffa65..5e0051a22c 100644
--- a/boost/asio/detail/atomic_count.hpp
+++ b/boost/asio/detail/atomic_count.hpp
@@ -31,10 +31,13 @@ namespace detail {
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
typedef long atomic_count;
+inline void increment(atomic_count& a, long b) { a += b; }
#elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
typedef std::atomic<long> atomic_count;
+inline void increment(atomic_count& a, long b) { a += b; }
#else // defined(BOOST_ASIO_HAS_STD_ATOMIC)
typedef boost::detail::atomic_count atomic_count;
+inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; }
#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC)
} // namespace detail
diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp
index 3f2314db9e..c47c0070c1 100644
--- a/boost/asio/detail/config.hpp
+++ b/boost/asio/detail/config.hpp
@@ -112,6 +112,20 @@
# endif // defined(__GNUC__)
#endif // !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR)
+// Compliant C++11 compilers put noexcept specifiers on error_category members.
+#if !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
+# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT
+# endif // !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
+#endif // !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
+
// Standard library support for arrays.
#if !defined(BOOST_ASIO_DISABLE_STD_ARRAY)
# if defined(__GNUC__)
@@ -163,7 +177,9 @@
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
# define BOOST_ASIO_HAS_STD_CHRONO
-# define BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))
+# define BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
@@ -355,4 +371,19 @@
# endif // !defined(UNDER_CE)
#endif // !defined(BOOST_ASIO_DISABLE_SIGNAL)
+// Support for the __thread keyword extension.
+#if !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)
+# if defined(__linux__)
+# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
+# if !defined(__INTEL_COMPILER) && !defined(__ICL)
+# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
+# elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
+# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
+# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
+# endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
+# endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# endif // defined(__linux__)
+#endif // !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)
+
#endif // BOOST_ASIO_DETAIL_CONFIG_HPP
diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp
index 2d26644ca8..8f66f74b1f 100644
--- a/boost/asio/detail/epoll_reactor.hpp
+++ b/boost/asio/detail/epoll_reactor.hpp
@@ -19,6 +19,7 @@
#if defined(BOOST_ASIO_HAS_EPOLL)
+#include <boost/cstdint.hpp>
#include <boost/limits.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/atomic_count.hpp>
@@ -59,6 +60,7 @@ public:
mutex mutex_;
epoll_reactor* reactor_;
int descriptor_;
+ boost::uint32_t registered_events_;
op_queue<reactor_op> op_queue_[max_ops];
bool shutdown_;
diff --git a/boost/asio/detail/fenced_block.hpp b/boost/asio/detail/fenced_block.hpp
index a362f5b56f..d9e8a04e8f 100644
--- a/boost/asio/detail/fenced_block.hpp
+++ b/boost/asio/detail/fenced_block.hpp
@@ -25,7 +25,8 @@
# include <boost/asio/detail/macos_fenced_block.hpp>
#elif defined(__sun)
# include <boost/asio/detail/solaris_fenced_block.hpp>
-#elif defined(__GNUC__) && defined(__arm__)
+#elif defined(__GNUC__) && defined(__arm__) \
+ && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
# include <boost/asio/detail/gcc_arm_fenced_block.hpp>
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
# include <boost/asio/detail/gcc_hppa_fenced_block.hpp>
@@ -54,7 +55,8 @@ typedef null_fenced_block fenced_block;
typedef macos_fenced_block fenced_block;
#elif defined(__sun)
typedef solaris_fenced_block fenced_block;
-#elif defined(__GNUC__) && defined(__arm__)
+#elif defined(__GNUC__) && defined(__arm__) \
+ && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
typedef gcc_arm_fenced_block fenced_block;
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
typedef gcc_hppa_fenced_block fenced_block;
diff --git a/boost/asio/detail/gcc_x86_fenced_block.hpp b/boost/asio/detail/gcc_x86_fenced_block.hpp
index b416b50d52..973165ab1e 100644
--- a/boost/asio/detail/gcc_x86_fenced_block.hpp
+++ b/boost/asio/detail/gcc_x86_fenced_block.hpp
@@ -40,17 +40,17 @@ public:
// Constructor for a full fenced block.
explicit gcc_x86_fenced_block(full_t)
{
- barrier1();
+ lbarrier();
}
// Destructor.
~gcc_x86_fenced_block()
{
- barrier2();
+ sbarrier();
}
private:
- static int barrier1()
+ static int barrier()
{
int r = 0, m = 1;
__asm__ __volatile__ (
@@ -61,12 +61,21 @@ private:
return r;
}
- static void barrier2()
+ static void lbarrier()
{
#if defined(__SSE2__)
- __asm__ __volatile__ ("mfence" ::: "memory");
+ __asm__ __volatile__ ("lfence" ::: "memory");
#else // defined(__SSE2__)
- barrier1();
+ barrier();
+#endif // defined(__SSE2__)
+ }
+
+ static void sbarrier()
+ {
+#if defined(__SSE2__)
+ __asm__ __volatile__ ("sfence" ::: "memory");
+#else // defined(__SSE2__)
+ barrier();
#endif // defined(__SSE2__)
}
};
diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp
index 771edea67c..073bd08825 100644
--- a/boost/asio/detail/impl/epoll_reactor.ipp
+++ b/boost/asio/detail/impl/epoll_reactor.ipp
@@ -127,7 +127,7 @@ void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
for (descriptor_state* state = registered_descriptors_.first();
state != 0; state = state->next_)
{
- ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.events = state->registered_events_;
ev.data.ptr = state;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev);
if (result != 0)
@@ -159,7 +159,8 @@ int epoll_reactor::register_descriptor(socket_type descriptor,
}
epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
+ descriptor_data->registered_events_ = ev.events;
ev.data.ptr = descriptor_data;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
if (result != 0)
@@ -184,7 +185,8 @@ int epoll_reactor::register_internal_descriptor(
}
epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
+ descriptor_data->registered_events_ = ev.events;
ev.data.ptr = descriptor_data;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
if (result != 0)
@@ -222,23 +224,47 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
if (descriptor_data->op_queue_[op_type].empty())
{
- if (allow_speculative)
+ if (allow_speculative
+ && (op_type != read_op
+ || descriptor_data->op_queue_[except_op].empty()))
{
- if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
+ if (op->perform())
{
- if (op->perform())
+ descriptor_lock.unlock();
+ io_service_.post_immediate_completion(op);
+ return;
+ }
+
+ if (op_type == write_op)
+ {
+ if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)
{
- descriptor_lock.unlock();
- io_service_.post_immediate_completion(op);
- return;
+ epoll_event ev = { 0, { 0 } };
+ ev.events = descriptor_data->registered_events_ | EPOLLOUT;
+ ev.data.ptr = descriptor_data;
+ if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev) == 0)
+ {
+ descriptor_data->registered_events_ |= ev.events;
+ }
+ else
+ {
+ op->ec_ = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+ io_service_.post_immediate_completion(op);
+ return;
+ }
}
}
}
else
{
+ if (op_type == write_op)
+ {
+ descriptor_data->registered_events_ |= EPOLLOUT;
+ }
+
epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
- | EPOLLOUT | EPOLLPRI | EPOLLET;
+ ev.events = descriptor_data->registered_events_;
ev.data.ptr = descriptor_data;
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
}
@@ -440,7 +466,7 @@ int epoll_reactor::do_epoll_create()
errno = EINVAL;
#endif // defined(EPOLL_CLOEXEC)
- if (fd == -1 && errno == EINVAL)
+ if (fd == -1 && (errno == EINVAL || errno == ENOSYS))
{
fd = epoll_create(epoll_size);
if (fd != -1)
diff --git a/boost/asio/detail/impl/socket_ops.ipp b/boost/asio/detail/impl/socket_ops.ipp
index 24d2d66ad1..16e95366e6 100644
--- a/boost/asio/detail/impl/socket_ops.ipp
+++ b/boost/asio/detail/impl/socket_ops.ipp
@@ -18,6 +18,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
+#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
diff --git a/boost/asio/detail/impl/strand_service.hpp b/boost/asio/detail/impl/strand_service.hpp
index 1d98d99055..7581852ff5 100644
--- a/boost/asio/detail/impl/strand_service.hpp
+++ b/boost/asio/detail/impl/strand_service.hpp
@@ -50,11 +50,6 @@ struct strand_service::on_dispatch_exit
}
};
-inline void strand_service::destroy(strand_service::implementation_type& impl)
-{
- impl = 0;
-}
-
template <typename Handler>
void strand_service::dispatch(strand_service::implementation_type& impl,
Handler handler)
diff --git a/boost/asio/detail/impl/strand_service.ipp b/boost/asio/detail/impl/strand_service.ipp
index 64e4cc00ce..1912d80f72 100644
--- a/boost/asio/detail/impl/strand_service.ipp
+++ b/boost/asio/detail/impl/strand_service.ipp
@@ -38,7 +38,7 @@ struct strand_service::on_do_complete_exit
impl_->mutex_.unlock();
if (more_handlers)
- owner_->post_immediate_completion(impl_);
+ owner_->post_private_immediate_completion(impl_);
}
};
diff --git a/boost/asio/detail/impl/task_io_service.hpp b/boost/asio/detail/impl/task_io_service.hpp
index 7cd7449e60..2cc7b7eea1 100644
--- a/boost/asio/detail/impl/task_io_service.hpp
+++ b/boost/asio/detail/impl/task_io_service.hpp
@@ -45,7 +45,7 @@ void task_io_service::dispatch(Handler handler)
BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
- post_immediate_completion(p.p);
+ post_non_private_immediate_completion(p.p);
p.v = p.p = 0;
}
}
diff --git a/boost/asio/detail/impl/task_io_service.ipp b/boost/asio/detail/impl/task_io_service.ipp
index 3d679c2dca..674df638fe 100644
--- a/boost/asio/detail/impl/task_io_service.ipp
+++ b/boost/asio/detail/impl/task_io_service.ipp
@@ -30,48 +30,67 @@ namespace boost {
namespace asio {
namespace detail {
+struct task_io_service::thread_info
+{
+ event* wakeup_event;
+ op_queue<operation> private_op_queue;
+ long private_outstanding_work;
+ thread_info* next;
+};
+
struct task_io_service::task_cleanup
{
~task_cleanup()
{
+ if (this_thread_->private_outstanding_work > 0)
+ {
+ boost::asio::detail::increment(
+ task_io_service_->outstanding_work_,
+ this_thread_->private_outstanding_work);
+ }
+ this_thread_->private_outstanding_work = 0;
+
// Enqueue the completed operations and reinsert the task at the end of
// the operation queue.
lock_->lock();
task_io_service_->task_interrupted_ = true;
- task_io_service_->op_queue_.push(*ops_);
+ task_io_service_->op_queue_.push(this_thread_->private_op_queue);
task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
}
task_io_service* task_io_service_;
mutex::scoped_lock* lock_;
- op_queue<operation>* ops_;
+ thread_info* this_thread_;
};
struct task_io_service::work_cleanup
{
~work_cleanup()
{
- task_io_service_->work_finished();
+ if (this_thread_->private_outstanding_work > 1)
+ {
+ boost::asio::detail::increment(
+ task_io_service_->outstanding_work_,
+ this_thread_->private_outstanding_work - 1);
+ }
+ else if (this_thread_->private_outstanding_work < 1)
+ {
+ task_io_service_->work_finished();
+ }
+ this_thread_->private_outstanding_work = 0;
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- if (!ops_->empty())
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ if (!this_thread_->private_op_queue.empty())
{
lock_->lock();
- task_io_service_->op_queue_.push(*ops_);
+ task_io_service_->op_queue_.push(this_thread_->private_op_queue);
}
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
}
task_io_service* task_io_service_;
mutex::scoped_lock* lock_;
- op_queue<operation>* ops_;
-};
-
-struct task_io_service::thread_info
-{
- event* wakeup_event;
- op_queue<operation>* private_op_queue;
- thread_info* next;
+ thread_info* this_thread_;
};
task_io_service::task_io_service(
@@ -131,19 +150,14 @@ std::size_t task_io_service::run(boost::system::error_code& ec)
thread_info this_thread;
event wakeup_event;
this_thread.wakeup_event = &wakeup_event;
- op_queue<operation> private_op_queue;
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- this_thread.private_op_queue = one_thread_ == 1 ? &private_op_queue : 0;
-#else // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- this_thread.private_op_queue = 0;
-#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ this_thread.private_outstanding_work = 0;
this_thread.next = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
std::size_t n = 0;
- for (; do_run_one(lock, this_thread, private_op_queue, ec); lock.lock())
+ for (; do_run_one(lock, this_thread, ec); lock.lock())
if (n != (std::numeric_limits<std::size_t>::max)())
++n;
return n;
@@ -161,14 +175,13 @@ std::size_t task_io_service::run_one(boost::system::error_code& ec)
thread_info this_thread;
event wakeup_event;
this_thread.wakeup_event = &wakeup_event;
- op_queue<operation> private_op_queue;
- this_thread.private_op_queue = 0;
+ this_thread.private_outstanding_work = 0;
this_thread.next = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
- return do_run_one(lock, this_thread, private_op_queue, ec);
+ return do_run_one(lock, this_thread, ec);
}
std::size_t task_io_service::poll(boost::system::error_code& ec)
@@ -182,29 +195,23 @@ std::size_t task_io_service::poll(boost::system::error_code& ec)
thread_info this_thread;
this_thread.wakeup_event = 0;
- op_queue<operation> private_op_queue;
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- this_thread.private_op_queue = one_thread_ == 1 ? &private_op_queue : 0;
-#else // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- this_thread.private_op_queue = 0;
-#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ this_thread.private_outstanding_work = 0;
this_thread.next = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
// We want to support nested calls to poll() and poll_one(), so any handlers
// that are already on a thread-private queue need to be put on to the main
// queue now.
if (one_thread_)
if (thread_info* outer_thread_info = ctx.next_by_key())
- if (outer_thread_info->private_op_queue)
- op_queue_.push(*outer_thread_info->private_op_queue);
+ op_queue_.push(outer_thread_info->private_op_queue);
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
std::size_t n = 0;
- for (; do_poll_one(lock, private_op_queue, ec); lock.lock())
+ for (; do_poll_one(lock, this_thread, ec); lock.lock())
if (n != (std::numeric_limits<std::size_t>::max)())
++n;
return n;
@@ -221,24 +228,22 @@ std::size_t task_io_service::poll_one(boost::system::error_code& ec)
thread_info this_thread;
this_thread.wakeup_event = 0;
- op_queue<operation> private_op_queue;
- this_thread.private_op_queue = 0;
+ this_thread.private_outstanding_work = 0;
this_thread.next = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
// We want to support nested calls to poll() and poll_one(), so any handlers
// that are already on a thread-private queue need to be put on to the main
// queue now.
if (one_thread_)
if (thread_info* outer_thread_info = ctx.next_by_key())
- if (outer_thread_info->private_op_queue)
- op_queue_.push(*outer_thread_info->private_op_queue);
+ op_queue_.push(outer_thread_info->private_op_queue);
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- return do_poll_one(lock, private_op_queue, ec);
+ return do_poll_one(lock, this_thread, ec);
}
void task_io_service::stop()
@@ -261,22 +266,33 @@ void task_io_service::reset()
void task_io_service::post_immediate_completion(task_io_service::operation* op)
{
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ if (one_thread_)
+ {
+ if (thread_info* this_thread = thread_call_stack::contains(this))
+ {
+ ++this_thread->private_outstanding_work;
+ this_thread->private_op_queue.push(op);
+ return;
+ }
+ }
+#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+
work_started();
- post_deferred_completion(op);
+ mutex::scoped_lock lock(mutex_);
+ op_queue_.push(op);
+ wake_one_thread_and_unlock(lock);
}
void task_io_service::post_deferred_completion(task_io_service::operation* op)
{
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
if (one_thread_)
{
if (thread_info* this_thread = thread_call_stack::contains(this))
{
- if (this_thread->private_op_queue)
- {
- this_thread->private_op_queue->push(op);
- return;
- }
+ this_thread->private_op_queue.push(op);
+ return;
}
}
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
@@ -291,16 +307,13 @@ void task_io_service::post_deferred_completions(
{
if (!ops.empty())
{
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
if (one_thread_)
{
if (thread_info* this_thread = thread_call_stack::contains(this))
{
- if (this_thread->private_op_queue)
- {
- this_thread->private_op_queue->push(ops);
- return;
- }
+ this_thread->private_op_queue.push(ops);
+ return;
}
}
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
@@ -311,6 +324,44 @@ void task_io_service::post_deferred_completions(
}
}
+void task_io_service::post_private_immediate_completion(
+ task_io_service::operation* op)
+{
+ work_started();
+ post_private_deferred_completion(op);
+}
+
+void task_io_service::post_private_deferred_completion(
+ task_io_service::operation* op)
+{
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ if (thread_info* this_thread = thread_call_stack::contains(this))
+ {
+ this_thread->private_op_queue.push(op);
+ return;
+ }
+#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+
+ mutex::scoped_lock lock(mutex_);
+ op_queue_.push(op);
+ wake_one_thread_and_unlock(lock);
+}
+
+void task_io_service::post_non_private_immediate_completion(
+ task_io_service::operation* op)
+{
+ work_started();
+ post_non_private_deferred_completion(op);
+}
+
+void task_io_service::post_non_private_deferred_completion(
+ task_io_service::operation* op)
+{
+ mutex::scoped_lock lock(mutex_);
+ op_queue_.push(op);
+ wake_one_thread_and_unlock(lock);
+}
+
void task_io_service::abandon_operations(
op_queue<task_io_service::operation>& ops)
{
@@ -320,7 +371,7 @@ void task_io_service::abandon_operations(
std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
task_io_service::thread_info& this_thread,
- op_queue<operation>& private_op_queue, const boost::system::error_code& ec)
+ const boost::system::error_code& ec)
{
while (!stopped_)
{
@@ -343,14 +394,13 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
else
lock.unlock();
- op_queue<operation> completed_ops;
- task_cleanup on_exit = { this, &lock, &completed_ops };
+ task_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.
- task_->run(!more_handlers, completed_ops);
+ task_->run(!more_handlers, this_thread.private_op_queue);
}
else
{
@@ -362,7 +412,7 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
lock.unlock();
// Ensure the count of outstanding work is decremented on block exit.
- work_cleanup on_exit = { this, &lock, &private_op_queue };
+ work_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
// Complete the operation. May throw an exception. Deletes the object.
@@ -385,7 +435,8 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
}
std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
- op_queue<operation>& private_op_queue, const boost::system::error_code& ec)
+ task_io_service::thread_info& this_thread,
+ const boost::system::error_code& ec)
{
if (stopped_)
return 0;
@@ -397,14 +448,13 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
lock.unlock();
{
- op_queue<operation> completed_ops;
- task_cleanup c = { this, &lock, &completed_ops };
+ task_cleanup c = { this, &lock, &this_thread };
(void)c;
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.
- task_->run(false, completed_ops);
+ task_->run(false, this_thread.private_op_queue);
}
o = op_queue_.front();
@@ -426,7 +476,7 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
lock.unlock();
// Ensure the count of outstanding work is decremented on block exit.
- work_cleanup on_exit = { this, &lock, &private_op_queue };
+ work_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
// Complete the operation. May throw an exception. Deletes the object.
diff --git a/boost/asio/detail/keyword_tss_ptr.hpp b/boost/asio/detail/keyword_tss_ptr.hpp
new file mode 100644
index 0000000000..10dd01a1f0
--- /dev/null
+++ b/boost/asio/detail/keyword_tss_ptr.hpp
@@ -0,0 +1,72 @@
+//
+// detail/keyword_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
+#define BOOST_ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class keyword_tss_ptr
+ : private noncopyable
+{
+public:
+ // Constructor.
+ keyword_tss_ptr()
+ {
+ }
+
+ // Destructor.
+ ~keyword_tss_ptr()
+ {
+ }
+
+ // Get the value.
+ operator T*() const
+ {
+ return value_;
+ }
+
+ // Set the value.
+ void operator=(T* value)
+ {
+ value_ = value;
+ }
+
+private:
+ static __thread T* value_;
+};
+
+template <typename T>
+__thread T* keyword_tss_ptr<T>::value_;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
+
+#endif // BOOST_ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
diff --git a/boost/asio/detail/strand_service.hpp b/boost/asio/detail/strand_service.hpp
index 4206346585..3a271b50d5 100644
--- a/boost/asio/detail/strand_service.hpp
+++ b/boost/asio/detail/strand_service.hpp
@@ -84,9 +84,6 @@ public:
// Construct a new strand implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
- // Destroy a strand implementation.
- void destroy(implementation_type& impl);
-
// Request the io_service to invoke the given handler.
template <typename Handler>
void dispatch(implementation_type& impl, Handler handler);
diff --git a/boost/asio/detail/task_io_service.hpp b/boost/asio/detail/task_io_service.hpp
index 7a0bcc5701..e05c3a7419 100644
--- a/boost/asio/detail/task_io_service.hpp
+++ b/boost/asio/detail/task_io_service.hpp
@@ -112,6 +112,16 @@ public:
// that work_started() was previously called for each operation.
BOOST_ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
+ // Request invocation of the given operation, preferring the thread-private
+ // queue if available, and return immediately. Assumes that work_started()
+ // has not yet been called for the operation.
+ BOOST_ASIO_DECL void post_private_immediate_completion(operation* op);
+
+ // Request invocation of the given operation, preferring the thread-private
+ // queue if available, and return immediately. Assumes that work_started()
+ // was previously called for the operation.
+ BOOST_ASIO_DECL void post_private_deferred_completion(operation* op);
+
// Process unfinished operations as part of a shutdown_service operation.
// Assumes that work_started() was previously called for the operations.
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
@@ -120,15 +130,23 @@ private:
// Structure containing information about an idle thread.
struct thread_info;
- // Run at most one operation. Blocks only if this_idle_thread is non-null.
+ // Request invocation of the given operation, avoiding the thread-private
+ // queue, and return immediately. Assumes that work_started() has not yet
+ // been called for the operation.
+ BOOST_ASIO_DECL void post_non_private_immediate_completion(operation* op);
+
+ // Request invocation of the given operation, avoiding the thread-private
+ // queue, and return immediately. Assumes that work_started() was previously
+ // called for the operation.
+ BOOST_ASIO_DECL void post_non_private_deferred_completion(operation* op);
+
+ // Run at most one operation. May block.
BOOST_ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,
- thread_info& this_thread, op_queue<operation>& private_op_queue,
- const boost::system::error_code& ec);
+ thread_info& this_thread, const boost::system::error_code& ec);
// Poll for at most one operation.
BOOST_ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock,
- op_queue<operation>& private_op_queue,
- const boost::system::error_code& ec);
+ thread_info& this_thread, const boost::system::error_code& ec);
// Stop the task and all idle threads.
BOOST_ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);
diff --git a/boost/asio/detail/tss_ptr.hpp b/boost/asio/detail/tss_ptr.hpp
index cdb09e71b8..d14a959447 100644
--- a/boost/asio/detail/tss_ptr.hpp
+++ b/boost/asio/detail/tss_ptr.hpp
@@ -19,6 +19,8 @@
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
# include <boost/asio/detail/null_tss_ptr.hpp>
+#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
+# include <boost/asio/detail/keyword_tss_ptr.hpp>
#elif defined(BOOST_WINDOWS)
# include <boost/asio/detail/win_tss_ptr.hpp>
#elif defined(BOOST_HAS_PTHREADS)
@@ -37,6 +39,8 @@ template <typename T>
class tss_ptr
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
: public null_tss_ptr<T>
+#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
+ : public keyword_tss_ptr<T>
#elif defined(BOOST_WINDOWS)
: public win_tss_ptr<T>
#elif defined(BOOST_HAS_PTHREADS)
@@ -48,6 +52,8 @@ public:
{
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
null_tss_ptr<T>::operator=(value);
+#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
+ keyword_tss_ptr<T>::operator=(value);
#elif defined(BOOST_WINDOWS)
win_tss_ptr<T>::operator=(value);
#elif defined(BOOST_HAS_PTHREADS)
diff --git a/boost/asio/detail/win_iocp_io_service.hpp b/boost/asio/detail/win_iocp_io_service.hpp
index c6ebf63e94..0e3bb0b8e6 100644
--- a/boost/asio/detail/win_iocp_io_service.hpp
+++ b/boost/asio/detail/win_iocp_io_service.hpp
@@ -135,6 +135,22 @@ public:
BOOST_ASIO_DECL void post_deferred_completions(
op_queue<win_iocp_operation>& ops);
+ // Request invocation of the given operation using the thread-private queue
+ // and return immediately. Assumes that work_started() has not yet been
+ // called for the operation.
+ void post_private_immediate_completion(win_iocp_operation* op)
+ {
+ post_immediate_completion(op);
+ }
+
+ // Request invocation of the given operation using the thread-private queue
+ // and return immediately. Assumes that work_started() was previously called
+ // for the operation.
+ void post_private_deferred_completion(win_iocp_operation* op)
+ {
+ post_deferred_completion(op);
+ }
+
// Process unfinished operations as part of a shutdown_service operation.
// Assumes that work_started() was previously called for the operations.
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp
index 72f1c35689..a7da0c1967 100644
--- a/boost/asio/ssl/detail/impl/engine.ipp
+++ b/boost/asio/ssl/detail/impl/engine.ipp
@@ -18,7 +18,10 @@
#include <boost/asio/detail/config.hpp>
#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+# include <boost/asio/detail/throw_error.hpp>
+# include <boost/asio/error.hpp>
# include <boost/asio/ssl/detail/engine.hpp>
+# include <boost/asio/ssl/error.hpp>
# include <boost/asio/ssl/verify_context.hpp>
#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
@@ -34,6 +37,13 @@ namespace detail {
engine::engine(SSL_CTX* context)
: ssl_(::SSL_new(context))
{
+ if (!ssl_)
+ {
+ boost::system::error_code ec(::ERR_get_error(),
+ boost::asio::error::get_ssl_category());
+ boost::asio::detail::throw_error(ec, "engine");
+ }
+
accept_mutex().init();
::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE);
diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp
index af33f6e039..fe62e6eabc 100644
--- a/boost/asio/ssl/detail/impl/openssl_init.ipp
+++ b/boost/asio/ssl/detail/impl/openssl_init.ipp
@@ -56,7 +56,9 @@ public:
::EVP_cleanup();
::CRYPTO_cleanup_all_ex_data();
::CONF_modules_unload(1);
+#if !defined(OPENSSL_NO_ENGINE)
::ENGINE_cleanup();
+#endif // !defined(OPENSSL_NO_ENGINE)
}
private:
diff --git a/boost/asio/ssl/detail/openssl_types.hpp b/boost/asio/ssl/detail/openssl_types.hpp
index 752fe587de..a3c3729332 100644
--- a/boost/asio/ssl/detail/openssl_types.hpp
+++ b/boost/asio/ssl/detail/openssl_types.hpp
@@ -18,7 +18,9 @@
#include <boost/asio/detail/config.hpp>
#include <openssl/conf.h>
#include <openssl/ssl.h>
-#include <openssl/engine.h>
+#if !defined(OPENSSL_NO_ENGINE)
+# include <openssl/engine.h>
+#endif // !defined(OPENSSL_NO_ENGINE)
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include <boost/asio/detail/socket_types.hpp>
diff --git a/boost/asio/strand.hpp b/boost/asio/strand.hpp
index ba82e602a8..6a1033f37e 100644
--- a/boost/asio/strand.hpp
+++ b/boost/asio/strand.hpp
@@ -105,7 +105,6 @@ public:
*/
~strand()
{
- service_.destroy(impl_);
}
/// Get the io_service associated with the strand.
diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp
index 21eeb51243..4fc894bb38 100644
--- a/boost/asio/version.hpp
+++ b/boost/asio/version.hpp
@@ -18,6 +18,6 @@
// BOOST_ASIO_VERSION % 100 is the sub-minor version
// BOOST_ASIO_VERSION / 100 % 1000 is the minor version
// BOOST_ASIO_VERSION / 100000 is the major version
-#define BOOST_ASIO_VERSION 100800 // 1.8.0
+#define BOOST_ASIO_VERSION 100802 // 1.8.2
#endif // BOOST_ASIO_VERSION_HPP
diff --git a/boost/asio/windows/basic_object_handle.hpp b/boost/asio/windows/basic_object_handle.hpp
index 161bb512f1..a94bb57e26 100644
--- a/boost/asio/windows/basic_object_handle.hpp
+++ b/boost/asio/windows/basic_object_handle.hpp
@@ -125,7 +125,7 @@ public:
void wait()
{
boost::system::error_code ec;
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "wait");
}
@@ -139,7 +139,7 @@ public:
*/
void wait(boost::system::error_code& ec)
{
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
}
/// Start an asynchronous wait on the object handle.
@@ -161,7 +161,7 @@ public:
template <typename WaitHandler>
void async_wait(WaitHandler handler)
{
- this->service.async_wait(this->implementation, handler);
+ this->get_service().async_wait(this->get_implementation(), handler);
}
};