Check that objects still exist when dispatching events to them
[libs/core.git] / source / io / eventdispatcher.cpp
1 #include <msp/time/utils.h>
2 #include "base.h"
3 #include "eventdispatcher.h"
4 #include "eventobject.h"
5 #include "poll.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace IO {
11
12 void EventDispatcher::add(EventObject &obj)
13 {
14         Slot slot(*this, obj);
15         set<Slot>::iterator i = objects.find(slot);
16         if(i==objects.end())
17         {
18                 i = objects.insert(slot).first;
19                 i->connect_signals();
20
21                 if(obj.get_events())
22                         poller.set_object(obj, obj.get_events());
23         }
24 }
25
26 void EventDispatcher::remove(EventObject &obj)
27 {
28         set<Slot>::iterator i = objects.find(Slot(*this, obj));
29         if(i!=objects.end())
30         {
31                 objects.erase(i);
32
33                 poller.set_object(obj, P_NONE);
34         }
35 }
36
37 void EventDispatcher::tick()
38 {
39         if(objects.empty())
40                 return;
41
42         if(poller.poll()>0)
43                 dispatch();
44 }
45
46 void EventDispatcher::tick(const Time::TimeDelta &dt)
47 {
48         if(objects.empty())
49                 return;
50
51         if(poller.poll(dt)>0)
52                 dispatch();
53 }
54
55 void EventDispatcher::tick(const Time::Timer &timer)
56 {
57         const Time::TimeStamp &timeout = timer.get_next_timeout();
58         if(timeout)
59                 tick(timeout-Time::now());
60         else
61                 tick();
62 }
63
64 void EventDispatcher::dispatch()
65 {
66         const vector<Poller::PolledObject> &result = poller.get_result();
67         for(vector<Poller::PolledObject>::const_iterator i=result.begin(); i!=result.end(); ++i)
68                 if(objects.count(Slot(*this, *i->object)))
69                         i->object->event(i->events);
70 }
71
72
73 EventDispatcher::Slot::Slot(EventDispatcher &d, EventObject &o):
74         disp(d),
75         obj(o)
76 { }
77
78 void EventDispatcher::Slot::connect_signals() const
79 {
80         obj.signal_events_changed.connect(sigc::mem_fun(this, &Slot::events_changed));
81         obj.signal_deleted.connect(sigc::mem_fun(this, &Slot::deleted));
82 }
83
84 void EventDispatcher::Slot::events_changed(PollEvent ev) const
85 {
86         disp.poller.set_object(obj, ev);
87 }
88
89 void EventDispatcher::Slot::deleted() const
90 {
91         disp.remove(obj);
92 }
93
94 } // namespace IO
95 } // namespace Msp