3 #include <msp/core/systemerror.h>
4 #include <msp/strings/format.h>
5 #include <msp/time/units.h>
14 using namespace Msp::IO;
16 inline int sys_poll_event(PollEvent event)
20 if(event&~(P_INPUT|P_PRIO|P_OUTPUT))
21 throw invalid_argument("sys_poll_event");
35 inline PollEvent poll_event_from_sys(int event)
37 PollEvent result = P_NONE;
43 result = result|P_INPUT;
45 result = result|P_PRIO;
47 result = result|P_OUTPUT;
49 result = result|P_ERROR;
55 inline PollEvent do_poll(Base &obj, PollEvent pe, int timeout)
61 DWORD ret = WaitForSingleObject(obj.get_event_handle(), timeout);
62 if(ret==WAIT_OBJECT_0)
64 else if(ret==WAIT_FAILED)
65 throw system_error("WaitForSingleObject");
69 pollfd pfd = { obj.get_event_handle(), sys_poll_event(pe), 0 };
71 int ret = ::poll(&pfd, 1, timeout);
77 throw system_error("poll");
80 return poll_event_from_sys(pfd.revents);
94 void Poller::set_object(Base &obj, PollEvent ev)
96 // Verify that the object has an event handle
98 obj.get_event_handle();
100 SlotMap::iterator i = objects.find(&obj);
104 i->second.events = ev;
113 if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
114 throw logic_error("Maximum number of wait objects reached");
116 objects.insert(SlotMap::value_type(&obj, Slot(&obj, ev)));
127 int Poller::poll(const Time::TimeDelta &timeout)
129 if(timeout<Time::zero)
130 throw invalid_argument("Poller::poll");
132 return do_poll(static_cast<int>(timeout/Time::msec));
135 void Poller::rebuild_pfd()
141 for(SlotMap::iterator i=objects.begin(); i!=objects.end(); ++i)
143 p.fd = i->second.object->get_event_handle();
145 p.events = sys_poll_event(i->second.events);
153 int Poller::do_poll(int timeout)
164 DWORD ret = WaitForMultipleObjects(pfd.size(), &pfd.front().fd, false, timeout);
165 if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+pfd.size())
167 SlotMap::iterator i = objects.begin();
168 advance(i, ret-WAIT_OBJECT_0);
169 poll_result.push_back(Slot(i->second.object, i->second.events));
173 else if(ret==WAIT_FAILED)
174 throw system_error("WaitForMultipleObjects");
178 int ret = ::poll(&pfd.front(), pfd.size(), timeout);
184 throw system_error("poll");
188 SlotMap::iterator j = objects.begin();
189 for(std::vector<pollfd>::iterator i=pfd.begin(); (i!=pfd.end() && n>0); ++i,++j)
192 poll_result.push_back(Slot(j->second.object, poll_event_from_sys(i->revents)));
201 PollEvent poll(Base &obj, PollEvent pe)
203 return do_poll(obj, pe, -1);
206 PollEvent poll(Base &obj, PollEvent pe, const Time::TimeDelta &timeout)
208 if(timeout<Time::zero)
209 throw invalid_argument("poll");
211 return do_poll(obj, pe, static_cast<int>(timeout/Time::msec));