3 This file is part of libmspio
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #include <msp/strings/formatter.h>
9 #include <msp/time/units.h>
17 using namespace Msp::IO;
19 inline int sys_poll_event(PollEvent event)
23 if(event&~(P_INPUT|P_PRIO|P_OUTPUT))
24 throw InvalidParameterValue("Invalid poll events");
38 inline PollEvent poll_event_from_sys(int event)
40 PollEvent result=P_NONE;
43 // Stop the compiler from complaining about unused parameter
47 result=result|P_INPUT;
51 result=result|P_OUTPUT;
53 result=result|P_ERROR;
59 inline PollEvent do_poll(Base &obj, PollEvent pe, int timeout)
65 DWORD ret=WaitForSingleObject(obj.get_event_handle(), timeout);
66 if(ret==WAIT_OBJECT_0)
68 else if(ret==WAIT_FAILED)
69 throw SystemError("Poll failed", GetLastError());
73 pollfd pfd={obj.get_event_handle(), sys_poll_event(pe), 0};
75 int ret=::poll(&pfd, 1, timeout);
81 throw SystemError("Poll failed", errno);
84 return poll_event_from_sys(pfd.revents);
97 void Poller::set_object(Base &obj, PollEvent ev)
99 // Verify that the object has an event handle
101 obj.get_event_handle();
103 SlotMap::iterator i=objects.find(&obj);
116 if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
117 throw InvalidState("Maximum number of wait objects reached");
119 objects.insert(SlotMap::value_type(&obj, Slot(&obj, ev)));
130 int Poller::poll(const Time::TimeDelta &timeout)
132 if(timeout<Time::zero)
133 throw InvalidParameterValue("Invalid timeout");
135 return do_poll(static_cast<int>(timeout/Time::msec));
138 void Poller::rebuild_pfd()
144 for(SlotMap::iterator i=objects.begin(); i!=objects.end(); ++i)
146 p.fd=i->second.object->get_event_handle();
148 p.events=sys_poll_event(i->second.events);
156 int Poller::do_poll(int timeout)
167 DWORD ret=WaitForMultipleObjects(pfd.size(), &pfd.front().fd, false, timeout);
168 if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+pfd.size())
170 SlotMap::iterator i=objects.begin();
171 advance(i, ret-WAIT_OBJECT_0);
172 poll_result.push_back(Slot(i->second.object, i->second.events));
176 else if(ret==WAIT_FAILED)
177 throw SystemError("Poll failed", GetLastError());
181 int ret=::poll(&pfd.front(), pfd.size(), timeout);
187 throw SystemError("Poll failed", errno);
191 SlotMap::iterator j=objects.begin();
192 for(std::vector<pollfd>::iterator i=pfd.begin(); (i!=pfd.end() && n>0); ++i,++j)
195 poll_result.push_back(Slot(j->second.object, poll_event_from_sys(i->revents)));
204 PollEvent poll(Base &obj, PollEvent pe)
206 return do_poll(obj, pe, -1);
209 PollEvent poll(Base &obj, PollEvent pe, const Time::TimeDelta &timeout)
211 if(timeout<Time::zero)
212 throw InvalidParameterValue("Invalid timeout");
214 return do_poll(obj, pe, static_cast<int>(timeout/Time::msec));