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