|
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