0fb9d22e03919476e95d52e09ca5faf10088241f
[libs/core.git] / source / io / unix / poll.cpp
1 #include <cerrno>
2 #include <msp/core/systemerror.h>
3 #include <poll.h>
4 #include "eventobject.h"
5 #include "handle.h"
6 #include "handle_private.h"
7 #include "poll.h"
8 #include "poll_platform.h"
9
10 using namespace std;
11
12 namespace {
13
14 using namespace Msp;
15 using namespace Msp::IO;
16
17 inline short int sys_poll_event(PollEvent event)
18 {
19         int result = 0;
20
21         if(event&~(P_INPUT|P_PRIO|P_OUTPUT))
22                 throw invalid_argument("sys_poll_event");
23
24         if(event&P_INPUT)
25                 result |= POLLIN;
26         if(event&P_PRIO)
27                 result |= POLLPRI;
28         if(event&P_OUTPUT)
29                 result |= POLLOUT;
30
31         return result;
32 }
33
34 inline PollEvent poll_event_from_sys(int event)
35 {
36         PollEvent result = P_NONE;
37
38         if(event&POLLIN)
39                 result = result|P_INPUT;
40         if(event&POLLPRI)
41                 result = result|P_PRIO;
42         if(event&POLLOUT)
43                 result = result|P_OUTPUT;
44         if(event&POLLERR)
45                 result = result|P_ERROR;
46         if(event&POLLHUP)
47                 result = result|P_HANGUP;
48
49         return result;
50 }
51
52 }
53
54
55 namespace Msp {
56 namespace IO {
57
58 void Poller::rebuild_array()
59 {
60         if(objs_changed)
61         {
62                 priv->pfd.clear();
63                 priv->pfd.reserve(objects.size());
64
65                 for(vector<Slot>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
66                 {
67                         pollfd p;
68                         p.fd = *i->object->get_event_handle();
69                         p.events = sys_poll_event(i->events);
70                         priv->pfd.push_back(p);
71                 }
72         }
73         else
74         {
75                 for(unsigned i=0; i<objects.size(); ++i)
76                         priv->pfd[i].events = sys_poll_event(objects[i].events);
77         }
78 }
79
80 void Poller::platform_poll(int timeout)
81 {
82         int ret = ::poll(&priv->pfd.front(), priv->pfd.size(), timeout);
83         if(ret==-1)
84         {
85                 if(errno==EINTR)
86                         return;
87                 else
88                         throw system_error("poll");
89         }
90
91         for(unsigned i=0; (i<objects.size() && ret>0); ++i)
92                 if(priv->pfd[i].revents)
93                 {
94                         poll_result.push_back(Slot(objects[i].object, poll_event_from_sys(priv->pfd[i].revents)));
95                         --ret;
96                 }
97 }
98
99
100 PollEvent platform_poll(EventObject &obj, PollEvent pe, int timeout)
101 {
102         pollfd pfd = { *obj.get_event_handle(), sys_poll_event(pe), 0 };
103
104         int ret = ::poll(&pfd, 1, timeout);
105         if(ret==-1)
106         {
107                 if(errno==EINTR)
108                         return P_NONE;
109                 else
110                         throw system_error("poll");
111         }
112
113         return poll_event_from_sys(pfd.revents);
114 }
115
116 } // namespace IO
117 } // namespace Msp