]> git.tdb.fi Git - libs/core.git/blob - source/poller.cpp
09193661a3c8f0ab82ac159e95b144b0fd78d227
[libs/core.git] / source / poller.cpp
1 /*
2 This file is part of libmspframework
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
5 */
6 #include "pollable.h"
7 #include "poller.h"
8
9 using namespace std;
10
11 namespace Msp {
12
13 Poller::Slot &Poller::add_pollable(Pollable *obj, short events)
14 {
15         MutexLock sl(slots_mutex);
16         
17         slots.push_back(new Slot(obj, events));
18         if(!pfd_mutex.trylock())
19         {
20                 rebuild_pfd();
21                 pfd_mutex.unlock();
22         }
23         else
24                 dirty=true;
25         return *slots.back();
26 }
27
28 int Poller::poll(int timeout)
29 {
30         slots_mutex.lock();
31         for(list<Slot *>::iterator i=slots.begin(); i!=slots.end();)
32         {
33                 if((*i)->get_object())
34                         ++i;
35                 else
36                 {
37                         delete *i;
38                         i=slots.erase(i);
39                         dirty=true;
40                 }
41         }
42
43         pfd_mutex.lock();
44         if(dirty)
45         {
46                 rebuild_pfd();
47                 dirty=false;
48         }
49         slots_mutex.unlock();
50         
51         int result=::poll(&pfd[0], pfd.size(), timeout);
52
53         if(result>0)
54         {
55                 list<Slot *>::iterator j=slots.begin();
56                 for(vector<pollfd>::iterator i=pfd.begin(); i!=pfd.end(); ++i)
57                 {
58                         if(i->revents&POLLNVAL)
59                                 dirty=true;
60                         else if(i->revents)
61                         {
62                                 while(j!=slots.end() && (!(*j)->get_object() || (*j)->get_object()->get_fd()!=i->fd))
63                                         ++j;
64                                 if(j==slots.end())
65                                         break;
66                                 (*j)->signal_event.emit(i->revents);
67                         }
68                 }
69         }
70
71         pfd_mutex.unlock();
72         
73         return result;
74 }
75
76 void Poller::rebuild_pfd()
77 {
78         pfd.clear();
79         pfd.reserve(slots.size());
80         for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
81         {
82                 if(!(*i)->get_object() || (*i)->get_object()->get_fd()<0)
83                         continue;
84
85                 pfd.push_back(pollfd());
86                 pfd.back().fd=(*i)->get_object()->get_fd();
87                 pfd.back().events=(*i)->get_events();
88         }
89 }
90
91 Poller::Slot::Slot(Pollable *o, short e):
92         obj(o),
93         events(e)
94 {
95         obj->signal_deleted.connect(sigc::mem_fun(this, &Slot::obj_deleted));
96 }
97
98 } // namespace Msp