]> git.tdb.fi Git - libs/core.git/blob - source/core/poller.cpp
4a623d4e1c9bd67672a04830df075281a3bf7e96
[libs/core.git] / source / core / 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 #ifdef WIN32
31         return 0;
32 #else
33         slots_mutex.lock();
34         for(list<Slot *>::iterator i=slots.begin(); i!=slots.end();)
35         {
36                 if((*i)->get_object())
37                         ++i;
38                 else
39                 {
40                         delete *i;
41                         i=slots.erase(i);
42                         dirty=true;
43                 }
44         }
45
46         pfd_mutex.lock();
47         if(dirty)
48         {
49                 rebuild_pfd();
50                 dirty=false;
51         }
52         slots_mutex.unlock();
53         
54         int result=::poll(&pfd[0], pfd.size(), timeout);
55
56         if(result>0)
57         {
58                 list<Slot *>::iterator j=slots.begin();
59                 for(vector<pollfd>::iterator i=pfd.begin(); i!=pfd.end(); ++i)
60                 {
61                         if(i->revents&POLLNVAL)
62                                 dirty=true;
63                         else if(i->revents)
64                         {
65                                 while(j!=slots.end() && (!(*j)->get_object() || (*j)->get_object()->get_fd()!=i->fd))
66                                         ++j;
67                                 if(j==slots.end())
68                                         break;
69                                 (*j)->signal_event.emit(i->revents);
70                         }
71                 }
72         }
73
74         pfd_mutex.unlock();
75         
76         return result;
77 #endif
78 }
79
80 void Poller::rebuild_pfd()
81 {
82         pfd.clear();
83         pfd.reserve(slots.size());
84         for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
85         {
86                 if(!(*i)->get_object() || (*i)->get_object()->get_fd()<0)
87                         continue;
88
89                 pfd.push_back(pollfd());
90                 pfd.back().fd=(*i)->get_object()->get_fd();
91                 pfd.back().events=(*i)->get_events();
92         }
93 }
94
95 Poller::Slot::Slot(Pollable *o, short e):
96         obj(o),
97         events(e)
98 {
99         obj->signal_deleted.connect(sigc::mem_fun(this, &Slot::obj_deleted));
100 }
101
102 } // namespace Msp