]> git.tdb.fi Git - libs/core.git/blobdiff - source/io/poll.cpp
Additional adjustments for Poller
[libs/core.git] / source / io / poll.cpp
index a58090792fcb06cf9c4a2a9049159ac7324524a8..a5d2d023c81d3f1ae730fc69d8d903b5546926db 100644 (file)
-#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),
+       events_changed(false),
        objs_changed(false)
 { }
 
@@ -117,34 +25,39 @@ void Poller::set_object(EventObject &obj, PollEvent ev)
        if(ev)
                obj.get_event_handle();
 
-       EventMap::iterator i = objects.find(&obj);
-       if(i!=objects.end())
-       {
-               if(ev)
-                       i->second = ev;
-               else
-                       objects.erase(i);
+       for(vector<PolledObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(i->object==&obj)
+               {
+                       if(ev)
+                               i->events = ev;
+                       else
+                       {
+                               *i = objects.back();
+                               objects.pop_back();
+                               objs_changed = true;
+                       }
+                       events_changed = true;
+                       return;
+               }
 
-               objs_changed = true;
-       }
-       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(EventMap::value_type(&obj, ev));
 
-               objs_changed = 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");
@@ -152,79 +65,28 @@ int Poller::poll(const Time::TimeDelta &timeout)
        return do_poll(static_cast<int>(timeout/Time::msec));
 }
 
-void Poller::rebuild_array()
+unsigned Poller::do_poll(int timeout)
 {
-#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)
+       if(objs_changed || events_changed)
        {
-               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)
                rebuild_array();
-
-       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;
+               events_changed = false;
+               objs_changed = false;
        }
-       else if(ret==WAIT_FAILED)
-               throw system_error("WaitForMultipleObjects");
 
-       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");
-       }
+       poll_result.clear();
 
-       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;
-               }
+       platform_poll(timeout);
 
-       return ret;
-#endif
+       return poll_result.size();
 }
 
 
+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)
@@ -232,7 +94,7 @@ 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