diff options
author | Anas Nashif <anas.nashif@intel.com> | 2013-08-26 08:15:55 -0400 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-08-26 08:15:55 -0400 |
commit | bb4dd8289b351fae6b55e303f189127a394a1edd (patch) | |
tree | 77c9c35a31b1459dd7988c2448e797d142530c41 /boost/asio | |
parent | 1a78a62555be32868418fe52f8e330c9d0f95d5a (diff) | |
download | boost-bb4dd8289b351fae6b55e303f189127a394a1edd.tar.gz boost-bb4dd8289b351fae6b55e303f189127a394a1edd.tar.bz2 boost-bb4dd8289b351fae6b55e303f189127a394a1edd.zip |
Imported Upstream version 1.51.0upstream/1.51.0
Diffstat (limited to 'boost/asio')
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); } }; |