#include <cerrno>
#include <stdexcept>
+#ifndef WIN32
+#include <poll.h>
+#endif
#include <msp/core/systemerror.h>
#include <msp/strings/format.h>
#include <msp/time/units.h>
namespace Msp {
namespace IO {
+struct Poller::Private
+{
+#ifdef WIN32
+ vector<HANDLE> handles;
+#else
+ vector<pollfd> pfd;
+#endif
+};
+
+
Poller::Poller():
- pfd_dirty(false)
+ priv(new Private),
+ objs_changed(false)
{ }
void Poller::set_object(Base &obj, PollEvent ev)
if(ev)
obj.get_event_handle();
- SlotMap::iterator i = objects.find(&obj);
+ EventMap::iterator i = objects.find(&obj);
if(i!=objects.end())
{
if(ev)
- i->second.events = ev;
+ i->second = ev;
else
objects.erase(i);
- pfd_dirty = true;
+ objs_changed = true;
}
else if(ev)
{
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)));
+ objects.insert(EventMap::value_type(&obj, ev));
- pfd_dirty = true;
+ objs_changed = true;
}
}
return do_poll(static_cast<int>(timeout/Time::msec));
}
-void Poller::rebuild_pfd()
+void Poller::rebuild_array()
{
- pfd.clear();
+#ifdef WIN32
+ priv->handles.clear();
- pollfd p;
+ for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
+ priv->handles.push_back(i->first->get_event_handle());
+#else
+ priv->pfd.clear();
- for(SlotMap::iterator i=objects.begin(); i!=objects.end(); ++i)
+ for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- p.fd = i->second.object->get_event_handle();
-#ifndef WIN32
- p.events = sys_poll_event(i->second.events);
-#endif
- pfd.push_back(p);
+ pollfd p;
+ p.fd = i->first->get_event_handle();
+ p.events = sys_poll_event(i->second);
+ priv->pfd.push_back(p);
}
+#endif
- pfd_dirty = false;
+ objs_changed = false;
}
int Poller::do_poll(int timeout)
{
- if(pfd_dirty)
- rebuild_pfd();
+ if(objs_changed)
+ rebuild_array();
poll_result.clear();
if(timeout<0)
timeout = INFINITE;
- DWORD ret = WaitForMultipleObjects(pfd.size(), &pfd.front().fd, false, timeout);
- if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+pfd.size())
+ DWORD ret = WaitForMultipleObjects(priv->handles.size(), &priv->handles.front(), false, timeout);
+ if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+priv->handles.size())
{
- SlotMap::iterator i = objects.begin();
+ EventMap::iterator i = objects.begin();
advance(i, ret-WAIT_OBJECT_0);
- poll_result.push_back(Slot(i->second.object, i->second.events));
+ poll_result.push_back(Slot(i->first, i->second));
return 1;
}
return 0;
#else
- int ret = ::poll(&pfd.front(), pfd.size(), timeout);
+ int ret = ::poll(&priv->pfd.front(), priv->pfd.size(), timeout);
if(ret==-1)
{
if(errno==EINTR)
}
int n = ret;
- SlotMap::iterator j = objects.begin();
- for(std::vector<pollfd>::iterator i=pfd.begin(); (i!=pfd.end() && n>0); ++i,++j)
+ EventMap::iterator j = objects.begin();
+ for(vector<pollfd>::iterator i=priv->pfd.begin(); (i!=priv->pfd.end() && n>0); ++i, ++j)
if(i->revents)
{
- poll_result.push_back(Slot(j->second.object, poll_event_from_sys(i->revents)));
+ poll_result.push_back(Slot(j->first, poll_event_from_sys(i->revents)));
--n;
}
#ifndef MSP_IO_POLL_H_
#define MSP_IO_POLL_H_
-#ifndef WIN32
-#include <poll.h>
-#endif
#include <list>
#include <map>
#include <vector>
#include <msp/time/timedelta.h>
-#include "types.h"
namespace Msp {
namespace IO {
Slot(Base *o, PollEvent e): object(o), events(e) { }
};
- typedef std::list<Slot> SlotSeq;
+ typedef std::list<Slot> SlotList;
private:
- typedef std::map<Base *, Slot> SlotMap;
+ typedef std::map<Base *, PollEvent> EventMap;
-#ifdef WIN32
- struct pollfd
- {
- Handle fd;
- };
-#endif
+ struct Private;
- SlotMap objects;
- std::vector<pollfd> pfd;
- bool pfd_dirty;
- SlotSeq poll_result;
+ EventMap objects;
+ Private *priv;
+ bool objs_changed;
+ SlotList poll_result;
public:
Poller();
int poll();
int poll(const Time::TimeDelta &);
private:
- void rebuild_pfd();
+ void rebuild_array();
int do_poll(int);
public:
- const SlotSeq &get_result() const { return poll_result; }
+ const SlotList &get_result() const { return poll_result; }
};
PollEvent poll(Base &, PollEvent);