]> git.tdb.fi Git - libs/core.git/blobdiff - source/core/poller.cpp
Rename to libmspcore
[libs/core.git] / source / core / poller.cpp
diff --git a/source/core/poller.cpp b/source/core/poller.cpp
new file mode 100644 (file)
index 0000000..4a623d4
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+This file is part of libmspframework
+Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+#include "pollable.h"
+#include "poller.h"
+
+using namespace std;
+
+namespace Msp {
+
+Poller::Slot &Poller::add_pollable(Pollable *obj, short events)
+{
+       MutexLock sl(slots_mutex);
+       
+       slots.push_back(new Slot(obj, events));
+       if(!pfd_mutex.trylock())
+       {
+               rebuild_pfd();
+               pfd_mutex.unlock();
+       }
+       else
+               dirty=true;
+       return *slots.back();
+}
+
+int Poller::poll(int timeout)
+{
+#ifdef WIN32
+       return 0;
+#else
+       slots_mutex.lock();
+       for(list<Slot *>::iterator i=slots.begin(); i!=slots.end();)
+       {
+               if((*i)->get_object())
+                       ++i;
+               else
+               {
+                       delete *i;
+                       i=slots.erase(i);
+                       dirty=true;
+               }
+       }
+
+       pfd_mutex.lock();
+       if(dirty)
+       {
+               rebuild_pfd();
+               dirty=false;
+       }
+       slots_mutex.unlock();
+       
+       int result=::poll(&pfd[0], pfd.size(), timeout);
+
+       if(result>0)
+       {
+               list<Slot *>::iterator j=slots.begin();
+               for(vector<pollfd>::iterator i=pfd.begin(); i!=pfd.end(); ++i)
+               {
+                       if(i->revents&POLLNVAL)
+                               dirty=true;
+                       else if(i->revents)
+                       {
+                               while(j!=slots.end() && (!(*j)->get_object() || (*j)->get_object()->get_fd()!=i->fd))
+                                       ++j;
+                               if(j==slots.end())
+                                       break;
+                               (*j)->signal_event.emit(i->revents);
+                       }
+               }
+       }
+
+       pfd_mutex.unlock();
+       
+       return result;
+#endif
+}
+
+void Poller::rebuild_pfd()
+{
+       pfd.clear();
+       pfd.reserve(slots.size());
+       for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
+       {
+               if(!(*i)->get_object() || (*i)->get_object()->get_fd()<0)
+                       continue;
+
+               pfd.push_back(pollfd());
+               pfd.back().fd=(*i)->get_object()->get_fd();
+               pfd.back().events=(*i)->get_events();
+       }
+}
+
+Poller::Slot::Slot(Pollable *o, short e):
+       obj(o),
+       events(e)
+{
+       obj->signal_deleted.connect(sigc::mem_fun(this, &Slot::obj_deleted));
+}
+
+} // namespace Msp