-#include <cerrno>
#include <stdexcept>
-#ifndef WIN32
-#include <poll.h>
-#endif
-#include <msp/core/systemerror.h>
-#include <msp/strings/format.h>
#include "eventobject.h"
-#include "handle.h"
-#include "handle_private.h"
#include "poll.h"
+#include "poll_platform.h"
using namespace std;
-namespace {
-
-using namespace Msp;
-using namespace Msp::IO;
-
-inline short 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
- (void)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(EventObject &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 {
-struct Poller::Private
-{
-#ifdef WIN32
- vector<HANDLE> handles;
-#else
- vector<pollfd> pfd;
-#endif
-};
-
-
Poller::Poller():
priv(new Private),
objs_changed(false)
return do_poll(static_cast<int>(timeout/Time::msec));
}
-void Poller::rebuild_array()
-{
-#ifdef WIN32
- priv->handles.clear();
-
- for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
- priv->handles.push_back(*i->first->get_event_handle());
-#else
- priv->pfd.clear();
-
- for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
- {
- pollfd p;
- p.fd = *i->first->get_event_handle();
- p.events = sys_poll_event(i->second);
- priv->pfd.push_back(p);
- }
-#endif
-
- objs_changed = false;
-}
-
int Poller::do_poll(int timeout)
{
if(objs_changed)
poll_result.clear();
-#ifdef WIN32
- if(timeout<0)
- timeout = INFINITE;
-
- DWORD ret = WaitForMultipleObjects(priv->handles.size(), &priv->handles.front(), false, timeout);
- if(/*ret>=WAIT_OBJECT_0 &&*/ ret<WAIT_OBJECT_0+priv->handles.size())
- {
- EventMap::iterator i = objects.begin();
- advance(i, ret-WAIT_OBJECT_0);
- poll_result.push_back(Slot(i->first, i->second));
-
- return 1;
- }
- else if(ret==WAIT_FAILED)
- throw system_error("WaitForMultipleObjects");
+ platform_poll(timeout);
- return 0;
-#else
- int ret = ::poll(&priv->pfd.front(), priv->pfd.size(), timeout);
- if(ret==-1)
- {
- if(errno==EINTR)
- return 0;
- else
- throw system_error("poll");
- }
+ return poll_result.size();
+}
- int n = ret;
- 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->first, poll_event_from_sys(i->revents)));
- --n;
- }
- return ret;
-#endif
-}
+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(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