$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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