can't use xgetbv instruction with apple gcc under OS X Lion
[ardour.git] / libs / pbd / crossthread.posix.cc
1 #include <poll.h>
2
3 CrossThreadChannel::CrossThreadChannel (bool non_blocking)
4         : receive_channel (0)
5 {
6         fds[0] = -1;
7         fds[1] = -1;
8
9         if (pipe (fds)) {
10                 error << "cannot create x-thread pipe for read (%2)" << ::strerror (errno) << endmsg;
11                 return;
12         }
13
14         if (non_blocking) {
15                 if (fcntl (fds[0], F_SETFL, O_NONBLOCK)) {
16                         error << "cannot set non-blocking mode for x-thread pipe (read) (" << ::strerror (errno) << ')' << endmsg;
17                         return;
18                 }
19                 
20                 if (fcntl (fds[1], F_SETFL, O_NONBLOCK)) {
21                         error << "cannot set non-blocking mode for x-thread pipe (write) (%2)" << ::strerror (errno) << ')' << endmsg;
22                         return;
23                 }
24         }
25
26         receive_channel = g_io_channel_unix_new (fds[0]);
27 }
28
29 CrossThreadChannel::~CrossThreadChannel ()
30 {
31         if (receive_channel) {
32                 g_io_channel_unref (receive_channel);
33         }
34
35         if (fds[0] >= 0) {
36                 close (fds[0]);
37                 fds[0] = -1;
38         } 
39
40         if (fds[1] >= 0) {
41                 close (fds[1]);
42                 fds[1] = -1;
43         } 
44 }
45
46 void
47 CrossThreadChannel::wakeup ()
48 {
49         char c = 0;
50         (void) ::write (fds[1], &c, 1);
51 }
52
53 void
54 CrossThreadChannel::drain ()
55 {
56         char buf[64];
57         while (::read (fds[0], buf, sizeof (buf)) > 0) {};
58 }
59
60 int
61 CrossThreadChannel::deliver (char msg)
62 {
63         return ::write (fds[1], &msg, 1);
64 }
65
66 bool
67 CrossThreadChannel::poll_for_request()
68 {
69         struct pollfd pfd[1];
70         pfd[0].fd = fds[0];
71         pfd[0].events = POLLIN|POLLERR|POLLHUP;
72         while(true) {
73                 if (poll (pfd, 1, -1) < 0) {
74                         if (errno == EINTR) {
75                                 continue;
76                         }
77                         break;
78                 }
79                 if (pfd[0].revents & ~POLLIN) {
80                         break;
81                 }
82
83                 if (pfd[0].revents & POLLIN) {
84                         return true;
85                 }
86         }
87         return false;
88 }
89
90 int 
91 CrossThreadChannel::receive (char& msg, bool wait)
92 {
93         if (wait) {
94                 if (!poll_for_request ()) {
95                         return -1;
96                 }
97         }
98         return ::read (fds[0], &msg, 1);
99 }