6 #include <msp/core/systemerror.h>
7 #include <msp/strings/format.h>
8 #include <msp/time/units.h>
9 #include "eventobject.h"
11 #include "handle_private.h"
19 using namespace Msp::IO;
21 inline short int sys_poll_event(PollEvent event)
25 if(event&~(P_INPUT|P_PRIO|P_OUTPUT))
26 throw invalid_argument("sys_poll_event");
40 inline PollEvent poll_event_from_sys(int event)
42 PollEvent result = P_NONE;
48 result = result|P_INPUT;
50 result = result|P_PRIO;
52 result = result|P_OUTPUT;
54 result = result|P_ERROR;
60 inline PollEvent do_poll(EventObject &obj, PollEvent pe, int timeout)
66 DWORD ret = WaitForSingleObject(*obj.get_event_handle(), timeout);
67 if(ret==WAIT_OBJECT_0)
69 else if(ret==WAIT_FAILED)
70 throw system_error("WaitForSingleObject");
74 pollfd pfd = { *obj.get_event_handle(), sys_poll_event(pe), 0 };
76 int ret = ::poll(&pfd, 1, timeout);
82 throw system_error("poll");
85 return poll_event_from_sys(pfd.revents);
95 struct Poller::Private
98 vector<HANDLE> handles;
110 void Poller::set_object(EventObject &obj, PollEvent ev)
112 // Verify that the object has an event handle
114 obj.get_event_handle();
116 EventMap::iterator i = objects.find(&obj);
129 if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
130 throw logic_error("Maximum number of wait objects reached");
132 objects.insert(EventMap::value_type(&obj, ev));
143 int Poller::poll(const Time::TimeDelta &timeout)
145 if(timeout<Time::zero)
146 throw invalid_argument("Poller::poll");
148 return do_poll(static_cast<int>(timeout/Time::msec));
151 void Poller::rebuild_array()
154 priv->handles.clear();
156 for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
157 priv->handles.push_back(*i->first->get_event_handle());
161 for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
164 p.fd = *i->first->get_event_handle();
165 p.events = sys_poll_event(i->second);
166 priv->pfd.push_back(p);
170 objs_changed = false;
173 int Poller::do_poll(int timeout)
184 DWORD ret = WaitForMultipleObjects(priv->handles.size(), &priv->handles.front(), false, timeout);
185 if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+priv->handles.size())
187 EventMap::iterator i = objects.begin();
188 advance(i, ret-WAIT_OBJECT_0);
189 poll_result.push_back(Slot(i->first, i->second));
193 else if(ret==WAIT_FAILED)
194 throw system_error("WaitForMultipleObjects");
198 int ret = ::poll(&priv->pfd.front(), priv->pfd.size(), timeout);
204 throw system_error("poll");
208 EventMap::iterator j = objects.begin();
209 for(vector<pollfd>::iterator i=priv->pfd.begin(); (i!=priv->pfd.end() && n>0); ++i, ++j)
212 poll_result.push_back(Slot(j->first, poll_event_from_sys(i->revents)));
221 PollEvent poll(EventObject &obj, PollEvent pe)
223 return do_poll(obj, pe, -1);
226 PollEvent poll(EventObject &obj, PollEvent pe, const Time::TimeDelta &timeout)
228 if(timeout<Time::zero)
229 throw invalid_argument("poll");
231 return do_poll(obj, pe, static_cast<int>(timeout/Time::msec));