summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/signaler.cpp50
-rw-r--r--src/signaler.hpp2
2 files changed, 46 insertions, 6 deletions
diff --git a/src/signaler.cpp b/src/signaler.cpp
index a511530..8778d1a 100644
--- a/src/signaler.cpp
+++ b/src/signaler.cpp
@@ -57,10 +57,15 @@
#include "signaler.hpp"
#include "likely.hpp"
+#include "stdint.hpp"
#include "err.hpp"
#include "fd.hpp"
#include "ip.hpp"
+#if defined ZMQ_HAVE_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
#if defined ZMQ_HAVE_WINDOWS
#include "windows.hpp"
#else
@@ -100,14 +105,19 @@ zmq::signaler_t::signaler_t ()
zmq::signaler_t::~signaler_t ()
{
-#if defined ZMQ_HAVE_WINDOWS
+#if defined ZMQ_HAVE_EVENTFD
+ int rc = close (r);
+ errno_assert (rc == 0);
+#elif defined ZMQ_HAVE_WINDOWS
int rc = closesocket (w);
wsa_assert (rc != SOCKET_ERROR);
rc = closesocket (r);
wsa_assert (rc != SOCKET_ERROR);
#else
- close (w);
- close (r);
+ int rc = close (w);
+ errno_assert (rc == 0);
+ rc = close (r);
+ errno_assert (rc == 0);
#endif
}
@@ -118,7 +128,11 @@ zmq::fd_t zmq::signaler_t::get_fd ()
void zmq::signaler_t::send ()
{
-#if defined ZMQ_HAVE_WINDOWS
+#if defined ZMQ_HAVE_EVENTFD
+ const uint64_t inc = 1;
+ ssize_t sz = write (w, &inc, sizeof (inc));
+ errno_assert (sz == sizeof (inc));
+#elif defined ZMQ_HAVE_WINDOWS
unsigned char dummy = 0;
int nbytes = ::send (w, (char*) &dummy, sizeof (dummy), 0);
wsa_assert (nbytes != SOCKET_ERROR);
@@ -188,6 +202,22 @@ int zmq::signaler_t::wait (int timeout_)
void zmq::signaler_t::recv ()
{
// Attempt to read a signal.
+#if defined ZMQ_HAVE_EVENTFD
+ uint64_t dummy;
+ ssize_t sz = read (r, &dummy, sizeof (dummy));
+ errno_assert (sz == sizeof (dummy));
+
+ // If we accidentally grabbed the next signal along with the current
+ // one, return it back to the eventfd object.
+ if (unlikely (dummy == 2)) {
+ const uint64_t inc = 1;
+ ssize_t sz = write (w, &inc, sizeof (inc));
+ errno_assert (sz == sizeof (inc));
+ return;
+ }
+
+ zmq_assert (dummy == 1);
+#else
unsigned char dummy;
#if defined ZMQ_HAVE_WINDOWS
int nbytes = ::recv (r, (char*) &dummy, sizeof (dummy), 0);
@@ -198,11 +228,21 @@ void zmq::signaler_t::recv ()
#endif
zmq_assert (nbytes == sizeof (dummy));
zmq_assert (dummy == 0);
+#endif
}
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
{
-#if defined ZMQ_HAVE_WINDOWS
+#if defined ZMQ_HAVE_EVENTFD
+
+ // Create eventfd object.
+ fd_t fd = eventfd (0, 0);
+ errno_assert (fd != -1);
+ *w_ = fd;
+ *r_ = fd;
+ return 0;
+
+#elif defined ZMQ_HAVE_WINDOWS
// Windows has no 'socketpair' function. CreatePipe is no good as pipe
// handles cannot be polled on. Here we create the socketpair by hand.
diff --git a/src/signaler.hpp b/src/signaler.hpp
index 2ebff41..dd474d9 100644
--- a/src/signaler.hpp
+++ b/src/signaler.hpp
@@ -49,7 +49,7 @@ namespace zmq
// to pass the signals.
static int make_fdpair (fd_t *r_, fd_t *w_);
- // Write & read end of the socketpair.
+ // Underlying write & read file descriptor.
fd_t w;
fd_t r;