2016-07-29 Update zh.po for Ardoru 5.0
[ardour.git] / libs / pbd / crossthread.posix.cc
index 44205e680d535d111240e91d8f86c633af768f0f..5035bc49da9d60ba6da8860a234650a4d1ea9bb6 100644 (file)
@@ -1,5 +1,8 @@
+#include <poll.h>
+
 CrossThreadChannel::CrossThreadChannel (bool non_blocking)
         : receive_channel (0)
+        , receive_source (0)
 {
        fds[0] = -1;
        fds[1] = -1;
@@ -14,7 +17,7 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking)
                        error << "cannot set non-blocking mode for x-thread pipe (read) (" << ::strerror (errno) << ')' << endmsg;
                        return;
                }
-               
+
                if (fcntl (fds[1], F_SETFL, O_NONBLOCK)) {
                        error << "cannot set non-blocking mode for x-thread pipe (write) (%2)" << ::strerror (errno) << ')' << endmsg;
                        return;
@@ -26,19 +29,20 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking)
 
 CrossThreadChannel::~CrossThreadChannel ()
 {
-        if (receive_channel) {
+       if (receive_channel) {
                 g_io_channel_unref (receive_channel);
+                receive_channel = 0;
         }
 
        if (fds[0] >= 0) {
                close (fds[0]);
                fds[0] = -1;
-       } 
+       }
 
        if (fds[1] >= 0) {
                close (fds[1]);
                fds[1] = -1;
-       } 
+       }
 }
 
 void
@@ -61,8 +65,37 @@ CrossThreadChannel::deliver (char msg)
         return ::write (fds[1], &msg, 1);
 }
 
-int 
-CrossThreadChannel::receive (char& msg)
+bool
+CrossThreadChannel::poll_for_request()
 {
+       struct pollfd pfd[1];
+       pfd[0].fd = fds[0];
+       pfd[0].events = POLLIN|POLLERR|POLLHUP;
+       while(true) {
+               if (poll (pfd, 1, -1) < 0) {
+                       if (errno == EINTR) {
+                               continue;
+                       }
+                       break;
+               }
+               if (pfd[0].revents & ~POLLIN) {
+                       break;
+               }
+
+               if (pfd[0].revents & POLLIN) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+int
+CrossThreadChannel::receive (char& msg, bool wait)
+{
+       if (wait) {
+               if (!poll_for_request ()) {
+                       return -1;
+               }
+       }
         return ::read (fds[0], &msg, 1);
 }