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