Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78708 - in branches/release: boost/asio/detail boost/asio/detail/impl boost/asio/ssl/detail boost/asio/ssl/detail/impl boost/asio/windows libs/asio/doc
From: chris_at_[hidden]
Date: 2012-05-28 06:16:11


Author: chris_kohlhoff
Date: 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
New Revision: 78708
URL: http://svn.boost.org/trac/boost/changeset/78708

Log:
Merge from trunk:

* Use correct basic_io_object member functions so that basic_object_handle works with c++11 compilers.

* Respect the OPENSSL_NO_ENGINE feature test #define.

* Last version's race-condition-related revert in the epoll_reactor was
  incomplete and broke out-of-band handling. Fixed epoll_reactor::start_op so
  that it is now exactly the same as the older, working version.

* Remove trailing whitespace.

* Eliminate a lock/unlock pair when rescheduling a strand.

* Added lazy registration for EPOLLOUT.

* Revision history.

Text files modified:
   branches/release/boost/asio/detail/epoll_reactor.hpp | 2 +
   branches/release/boost/asio/detail/impl/epoll_reactor.ipp | 48 ++++++++++++++++++++++++++++++---------
   branches/release/boost/asio/detail/impl/strand_service.ipp | 2
   branches/release/boost/asio/detail/impl/task_io_service.ipp | 44 +++++++++++++++++++++++++++++-------
   branches/release/boost/asio/detail/task_io_service.hpp | 10 ++++++++
   branches/release/boost/asio/detail/win_iocp_io_service.hpp | 16 +++++++++++++
   branches/release/boost/asio/ssl/detail/impl/openssl_init.ipp | 2 +
   branches/release/boost/asio/ssl/detail/openssl_types.hpp | 4 ++
   branches/release/boost/asio/windows/basic_object_handle.hpp | 6 ++--
   branches/release/libs/asio/doc/history.qbk | 12 ++++++++++
   10 files changed, 121 insertions(+), 25 deletions(-)

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 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -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 @@
     mutex mutex_;
     epoll_reactor* reactor_;
     int descriptor_;
+ boost::uint32_t registered_events_;
     op_queue<reactor_op> op_queue_[max_ops];
     bool shutdown_;
 

Modified: branches/release/boost/asio/detail/impl/epoll_reactor.ipp
==============================================================================
--- branches/release/boost/asio/detail/impl/epoll_reactor.ipp (original)
+++ branches/release/boost/asio/detail/impl/epoll_reactor.ipp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -127,7 +127,7 @@
     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 @@
   }
 
   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 @@
   }
 
   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 @@
 
   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);
     }

Modified: branches/release/boost/asio/detail/impl/strand_service.ipp
==============================================================================
--- branches/release/boost/asio/detail/impl/strand_service.ipp (original)
+++ branches/release/boost/asio/detail/impl/strand_service.ipp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -38,7 +38,7 @@
     impl_->mutex_.unlock();
 
     if (more_handlers)
- owner_->post_immediate_completion(impl_);
+ owner_->post_private_immediate_completion(impl_);
   }
 };
 

Modified: branches/release/boost/asio/detail/impl/task_io_service.ipp
==============================================================================
--- branches/release/boost/asio/detail/impl/task_io_service.ipp (original)
+++ branches/release/boost/asio/detail/impl/task_io_service.ipp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -53,7 +53,7 @@
   {
     task_io_service_->work_finished();
 
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
     if (!ops_->empty())
     {
       lock_->lock();
@@ -132,8 +132,8 @@
   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;
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ this_thread.private_op_queue = &private_op_queue;
 #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)
@@ -183,8 +183,8 @@
   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;
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
+ this_thread.private_op_queue = &private_op_queue;
 #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)
@@ -193,7 +193,7 @@
 
   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.
@@ -228,7 +228,7 @@
 
   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.
@@ -267,7 +267,7 @@
 
 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))
@@ -291,7 +291,7 @@
 {
   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))
@@ -311,6 +311,32 @@
   }
 }
 
+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))
+ {
+ if (this_thread->private_op_queue)
+ {
+ 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::abandon_operations(
     op_queue<task_io_service::operation>& ops)
 {

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 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -112,6 +112,16 @@
   // 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 using the thread-private queue
+ // 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 using the thread-private queue
+ // 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);

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 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -135,6 +135,22 @@
   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);

Modified: branches/release/boost/asio/ssl/detail/impl/openssl_init.ipp
==============================================================================
--- branches/release/boost/asio/ssl/detail/impl/openssl_init.ipp (original)
+++ branches/release/boost/asio/ssl/detail/impl/openssl_init.ipp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -56,7 +56,9 @@
     ::EVP_cleanup();
     ::CRYPTO_cleanup_all_ex_data();
     ::CONF_modules_unload(1);
+#if !defined(OPENSSL_NO_ENGINE)
     ::ENGINE_cleanup();
+#endif // !defined(OPENSSL_NO_ENGINE)
   }
 
 private:

Modified: branches/release/boost/asio/ssl/detail/openssl_types.hpp
==============================================================================
--- branches/release/boost/asio/ssl/detail/openssl_types.hpp (original)
+++ branches/release/boost/asio/ssl/detail/openssl_types.hpp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -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>

Modified: branches/release/boost/asio/windows/basic_object_handle.hpp
==============================================================================
--- branches/release/boost/asio/windows/basic_object_handle.hpp (original)
+++ branches/release/boost/asio/windows/basic_object_handle.hpp 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -125,7 +125,7 @@
   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 @@
    */
   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 @@
   template <typename WaitHandler>
   void async_wait(WaitHandler handler)
   {
- this->service.async_wait(this->implementation, handler);
+ this->get_service().async_wait(this->get_implementation(), handler);
   }
 };
 

Modified: branches/release/libs/asio/doc/history.qbk
==============================================================================
--- branches/release/libs/asio/doc/history.qbk (original)
+++ branches/release/libs/asio/doc/history.qbk 2012-05-28 06:16:08 EDT (Mon, 28 May 2012)
@@ -7,6 +7,18 @@
 
 [section:history Revision History]
 
+[heading Asio 1.8.1 / Boost 1.50]
+
+* Changed the `epoll_reactor` backend to do lazy registration for `EPOLLOUT`
+ events.
+* Fixed the `epoll_reactor` handling of out-of-band data, which was broken by
+ an incomplete fix in the last release.
+* Changed Asio's SSL wrapper to respect OpenSSL's `OPENSSL_NO_ENGINE` feature
+ test `#define`.
+* Fixed `windows::object_handle` so that it works with Windows compilers that
+ support C++11 move semantics (such as [^g++]).
+* Improved the performance of strand rescheduling.
+
 [heading Asio 1.8.0 / Boost 1.49]
 
 * Added a new class template `basic_waitable_timer` based around the C++11 clock


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