update readme
[c11concurrency-benchmarks.git] / iris / src / notifier.cpp
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <poll.h>
6
7 #include <string>
8 #include <system_error>
9
10 #include <notifier.h>
11
12 using namespace iris;
13
14 notifier::notifier() {
15     if (::pipe(m_pipe)) {
16         std::string error_str = "failed to call pipe(), reason:";
17         error_str += strerror(errno);
18         throw std::system_error(std::error_code(errno, std::system_category()), error_str);
19     }   
20     if (fcntl(m_pipe[1], F_SETFL, O_NONBLOCK)) {
21         std::string error_str = "failed to set piep's write side to nonblock mode, reason:";
22         error_str += strerror(errno);
23         throw std::system_error(std::error_code(errno, std::system_category()), error_str);
24     }
25 }
26
27 notifier::~notifier() {
28     close(m_pipe[0]);
29     close(m_pipe[1]);
30 }
31
32 void notifier::notify(const ntf_t & ntf) {
33     size_t written = 0;
34     while (written < sizeof(ntf_t)) {
35         int n = write(m_pipe[1], (char *)&ntf, sizeof(ntf_t) - written);
36         if (n <= 0) {
37             if (errno == EINTR)
38                 continue;
39             break;
40         }
41         written += n;
42     }
43 }
44
45 bool notifier::wait(long timeout, std::vector<ntf_t> & ntfs) {
46     struct pollfd pfd;
47     pfd.fd = m_pipe[0];
48     pfd.events = POLLIN;
49
50     if(poll(&pfd, 1, timeout) == 1) {
51         int flags = fcntl(m_pipe[0], F_GETFL, 0);
52         flags |= O_NONBLOCK;
53         fcntl(m_pipe[0], F_SETFL, flags);
54         while (true) {
55             ntf_t ntf;
56             size_t readn = 0;
57             while (readn < sizeof(ntf_t)) {
58                 int n = read(m_pipe[0], &ntf, sizeof(ntf_t) - readn);
59                 if (n <= 0) {
60                     if (errno == EINTR)
61                         continue;
62                     break;
63                 }
64                 readn += n;
65             }
66             if (readn >= sizeof(ntf_t)) {
67                 ntfs.push_back(ntf);
68             } else {
69                 break;
70             }
71         }
72         flags &= ~O_NONBLOCK;
73         fcntl(m_pipe[0], F_SETFL, flags);
74
75         return true;
76     }
77
78     return false;
79 }