6272b4dbf143e26aba3331117e284d1b690dbac7
[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         priv->pfd.clear();
61
62         for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
63         {
64                 pollfd p;
65                 p.fd = *i->first->get_event_handle();
66                 p.events = sys_poll_event(i->second);
67                 priv->pfd.push_back(p);
68         }
69
70         objs_changed = false;
71 }
72
73 void Poller::platform_poll(int timeout)
74 {
75         int ret = ::poll(&priv->pfd.front(), priv->pfd.size(), timeout);
76         if(ret==-1)
77         {
78                 if(errno==EINTR)
79                         return;
80                 else
81                         throw system_error("poll");
82         }
83
84         EventMap::iterator j = objects.begin();
85         for(vector<pollfd>::iterator i=priv->pfd.begin(); (i!=priv->pfd.end() && ret>0); ++i, ++j)
86                 if(i->revents)
87                 {
88                         poll_result.push_back(Slot(j->first, poll_event_from_sys(i->revents)));
89                         --ret;
90                 }
91 }
92
93
94 PollEvent platform_poll(EventObject &obj, PollEvent pe, int timeout)
95 {
96         pollfd pfd = { *obj.get_event_handle(), sys_poll_event(pe), 0 };
97
98         int ret = ::poll(&pfd, 1, timeout);
99         if(ret==-1)
100         {
101                 if(errno==EINTR)
102                         return P_NONE;
103                 else
104                         throw system_error("poll");
105         }
106
107         return poll_event_from_sys(pfd.revents);
108 }
109
110 } // namespace IO
111 } // namespace Msp