-#include <errno.h>
#include <stdexcept>
-#include <msp/core/systemerror.h>
-#include <msp/strings/formatter.h>
-#include <msp/time/units.h>
-#include "base.h"
+#include <msp/core/algorithm.h>
+#include "eventobject.h"
#include "poll.h"
+#include "poll_platform.h"
using namespace std;
-namespace {
-
-using namespace Msp;
-using namespace Msp::IO;
-
-inline int sys_poll_event(PollEvent event)
-{
- int result = 0;
-
- if(event&~(P_INPUT|P_PRIO|P_OUTPUT))
- throw invalid_argument("sys_poll_event");
-
-#ifndef WIN32
- if(event&P_INPUT)
- result |= POLLIN;
- if(event&P_PRIO)
- result |= POLLPRI;
- if(event&P_OUTPUT)
- result |= POLLOUT;
-#endif
-
- return result;
-}
-
-inline PollEvent poll_event_from_sys(int event)
-{
- PollEvent result = P_NONE;
-
-#ifdef WIN32
- // Stop the compiler from complaining about unused parameter
- event = event;
-#else
- if(event&POLLIN)
- result = result|P_INPUT;
- if(event&POLLPRI)
- result = result|P_PRIO;
- if(event&POLLOUT)
- result = result|P_OUTPUT;
- if(event&POLLERR)
- result = result|P_ERROR;
-#endif
-
- return result;
-}
-
-inline PollEvent do_poll(Base &obj, PollEvent pe, int timeout)
-{
-#ifdef WIN32
- if(timeout<0)
- timeout = INFINITE;
-
- DWORD ret = WaitForSingleObject(obj.get_event_handle(), timeout);
- if(ret==WAIT_OBJECT_0)
- return pe;
- else if(ret==WAIT_FAILED)
- throw system_error("WaitForSingleObject");
-
- return P_NONE;
-#else
- pollfd pfd = {obj.get_event_handle(), sys_poll_event(pe), 0};
-
- int ret = ::poll(&pfd, 1, timeout);
- if(ret==-1)
- {
- if(errno==EINTR)
- return P_NONE;
- else
- throw system_error("poll");
- }
-
- return poll_event_from_sys(pfd.revents);
-#endif
-}
-
-}
-
namespace Msp {
namespace IO {
Poller::Poller():
- pfd_dirty(false)
+ priv(new Private)
{ }
-void Poller::set_object(Base &obj, PollEvent ev)
+Poller::~Poller()
+{
+ delete priv;
+}
+
+void Poller::set_object(EventObject &obj, PollEvent ev)
{
// Verify that the object has an event handle
if(ev)
obj.get_event_handle();
- SlotMap::iterator i = objects.find(&obj);
+ auto i = find_member(objects, &obj, &PolledObject::object);
if(i!=objects.end())
{
if(ev)
- i->second.events = ev;
+ i->events = ev;
else
- objects.erase(i);
-
- pfd_dirty = true;
+ {
+ *i = objects.back();
+ objects.pop_back();
+ objs_changed = true;
+ }
+ events_changed = true;
+ return;
}
- else if(ev)
- {
-#ifdef WIN32
- if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
- throw logic_error("Maximum number of wait objects reached");
+
+ if(!ev)
+ return;
+
+#ifdef _WIN32
+ if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
+ throw logic_error("Maximum number of wait objects reached");
#endif
- objects.insert(SlotMap::value_type(&obj, Slot(&obj, ev)));
- pfd_dirty = true;
- }
+ objects.push_back(PolledObject(&obj, ev));
+ objs_changed = true;
}
-int Poller::poll()
+unsigned Poller::poll()
{
return do_poll(-1);
}
-int Poller::poll(const Time::TimeDelta &timeout)
+unsigned Poller::poll(const Time::TimeDelta &timeout)
{
if(timeout<Time::zero)
throw invalid_argument("Poller::poll");
return do_poll(static_cast<int>(timeout/Time::msec));
}
-void Poller::rebuild_pfd()
+unsigned Poller::do_poll(int timeout)
{
- pfd.clear();
-
- pollfd p;
-
- for(SlotMap::iterator i=objects.begin(); i!=objects.end(); ++i)
+ if(objs_changed || events_changed)
{
- p.fd = i->second.object->get_event_handle();
-#ifndef WIN32
- p.events = sys_poll_event(i->second.events);
-#endif
- pfd.push_back(p);
+ rebuild_array();
+ events_changed = false;
+ objs_changed = false;
}
- pfd_dirty = false;
-}
-
-int Poller::do_poll(int timeout)
-{
- if(pfd_dirty)
- rebuild_pfd();
-
poll_result.clear();
-#ifdef WIN32
- if(timeout<0)
- timeout = INFINITE;
+ platform_poll(timeout);
- DWORD ret = WaitForMultipleObjects(pfd.size(), &pfd.front().fd, false, timeout);
- if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+pfd.size())
- {
- SlotMap::iterator i = objects.begin();
- advance(i, ret-WAIT_OBJECT_0);
- poll_result.push_back(Slot(i->second.object, i->second.events));
-
- return 1;
- }
- else if(ret==WAIT_FAILED)
- throw system_error("WaitForMultipleObjects");
-
- return 0;
-#else
- int ret = ::poll(&pfd.front(), pfd.size(), timeout);
- if(ret==-1)
- {
- if(errno==EINTR)
- return 0;
- else
- throw system_error("poll");
- }
-
- int n = ret;
- SlotMap::iterator j = objects.begin();
- for(std::vector<pollfd>::iterator i=pfd.begin(); (i!=pfd.end() && n>0); ++i,++j)
- if(i->revents)
- {
- poll_result.push_back(Slot(j->second.object, poll_event_from_sys(i->revents)));
- --n;
- }
-
- return ret;
-#endif
+ return poll_result.size();
}
-PollEvent poll(Base &obj, PollEvent pe)
+PollEvent platform_poll(EventObject &, PollEvent, int);
+
+PollEvent poll(EventObject &obj, PollEvent pe)
{
- return do_poll(obj, pe, -1);
+ return platform_poll(obj, pe, -1);
}
-PollEvent poll(Base &obj, PollEvent pe, const Time::TimeDelta &timeout)
+PollEvent poll(EventObject &obj, PollEvent pe, const Time::TimeDelta &timeout)
{
if(timeout<Time::zero)
throw invalid_argument("poll");
- return do_poll(obj, pe, static_cast<int>(timeout/Time::msec));
+ return platform_poll(obj, pe, static_cast<int>(timeout/Time::msec));
}
} // namespace IO