Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50961 - trunk/boost/asio/detail
From: chris_at_[hidden]
Date: 2009-02-02 01:18:59


Author: chris_kohlhoff
Date: 2009-02-02 01:18:59 EST (Mon, 02 Feb 2009)
New Revision: 50961
URL: http://svn.boost.org/trac/boost/changeset/50961

Log:
Use a pipe if eventfd is not supported at runtime. Fixes #2683.

Text files modified:
   trunk/boost/asio/detail/eventfd_select_interrupter.hpp | 56 +++++++++++++++++++++++++++++++--------
   1 files changed, 44 insertions(+), 12 deletions(-)

Modified: trunk/boost/asio/detail/eventfd_select_interrupter.hpp
==============================================================================
--- trunk/boost/asio/detail/eventfd_select_interrupter.hpp (original)
+++ trunk/boost/asio/detail/eventfd_select_interrupter.hpp 2009-02-02 01:18:59 EST (Mon, 02 Feb 2009)
@@ -58,9 +58,9 @@
   eventfd_select_interrupter()
   {
 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
- read_descriptor_ = syscall(__NR_eventfd, 0);
+ write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
 #else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
- read_descriptor_ = ::eventfd(0, 0);
+ write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
 #endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
     if (read_descriptor_ != -1)
     {
@@ -68,16 +68,29 @@
     }
     else
     {
- boost::system::error_code ec(errno,
- boost::asio::error::get_system_category());
- boost::system::system_error e(ec, "eventfd_select_interrupter");
- boost::throw_exception(e);
+ int pipe_fds[2];
+ if (pipe(pipe_fds) == 0)
+ {
+ read_descriptor_ = pipe_fds[0];
+ ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+ write_descriptor_ = pipe_fds[1];
+ ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+ }
+ else
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ boost::system::system_error e(ec, "eventfd_select_interrupter");
+ boost::throw_exception(e);
+ }
     }
   }
 
   // Destructor.
   ~eventfd_select_interrupter()
   {
+ if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
+ ::close(write_descriptor_);
     if (read_descriptor_ != -1)
       ::close(read_descriptor_);
   }
@@ -86,18 +99,31 @@
   void interrupt()
   {
     uint64_t counter(1UL);
- int result = ::write(read_descriptor_, &counter, sizeof(uint64_t));
+ int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
     (void)result;
   }
 
   // Reset the select interrupt. Returns true if the call was interrupted.
   bool reset()
   {
- // Only perform one read. The kernel maintains an atomic counter.
- uint64_t counter(0);
- int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
- bool was_interrupted = (bytes_read > 0);
- return was_interrupted;
+ if (write_descriptor_ == read_descriptor_)
+ {
+ // Only perform one read. The kernel maintains an atomic counter.
+ uint64_t counter(0);
+ int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+ bool was_interrupted = (bytes_read > 0);
+ return was_interrupted;
+ }
+ else
+ {
+ // Clear all data from the pipe.
+ char data[1024];
+ int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ bool was_interrupted = (bytes_read > 0);
+ while (bytes_read == sizeof(data))
+ bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ return was_interrupted;
+ }
   }
 
   // Get the read descriptor to be passed to select.
@@ -112,6 +138,12 @@
   // 64bit value will be written on the other end of the connection and this
   // descriptor will become readable.
   int read_descriptor_;
+
+ // The write end of a connection used to interrupt the select call. A single
+ // 64bit non-zero value may be written to this to wake up the select which is
+ // waiting for the other end to become readable. This descriptor will only
+ // differ from the read descriptor when a pipe is used.
+ int write_descriptor_;
 };
 
 } // namespace detail


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