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 //cout<<"poller set_object "<<&obj<<' '<<ev<<'\n';
105 SlotMap::iterator i=objects.find(&obj);
118 if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
119 throw InvalidState("Maximum number of wait objects reached");
121 objects.insert(SlotMap::value_type(&obj, Slot(&obj, ev)));
132 int Poller::poll(const Time::TimeDelta &timeout)
134 if(timeout<Time::zero)
135 throw InvalidParameterValue("Invalid timeout");
137 return do_poll(static_cast<int>(timeout/Time::msec));
140 void Poller::rebuild_pfd()
146 for(SlotMap::iterator i=objects.begin(); i!=objects.end(); ++i)
148 p.fd=i->second.object->get_event_handle();
150 p.events=sys_poll_event(i->second.events);
158 int Poller::do_poll(int timeout)
166 throw InvalidState("Nothing to poll");
172 DWORD ret=WaitForMultipleObjects(pfd.size(), reinterpret_cast<HANDLE *>(&pfd.front()), false, timeout);
173 if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+pfd.size())
175 SlotMap::iterator i=objects.begin();
176 advance(i, ret-WAIT_OBJECT_0);
177 poll_result.push_back(Slot(i->second.object, i->second.events));
181 else if(ret==WAIT_FAILED)
182 throw SystemError("Poll failed", GetLastError());
186 int ret=::poll(&pfd.front(), pfd.size(), timeout);
192 throw SystemError("Poll failed", errno);
196 SlotMap::iterator j=objects.begin();
197 for(std::vector<pollfd>::iterator i=pfd.begin(); (i!=pfd.end() && n>0); ++i,++j)
200 poll_result.push_back(Slot(j->second.object, poll_event_from_sys(i->revents)));
209 PollEvent poll(Base &obj, PollEvent pe)
211 return do_poll(obj, pe, -1);
214 PollEvent poll(Base &obj, PollEvent pe, const Time::TimeDelta &timeout)
216 if(timeout<Time::zero)
217 throw InvalidParameterValue("Invalid timeout");
219 return do_poll(obj, pe, static_cast<int>(timeout/Time::msec));