#include "eventobject.h"
#include "poll.h"
+using namespace std;
+
namespace Msp {
namespace IO {
-EventDispatcher::EventDispatcher()
-{ }
-
-EventDispatcher::~EventDispatcher()
-{ }
-
void EventDispatcher::add(EventObject &obj)
{
- SlotMap::iterator i = objects.find(&obj);
+ Slot slot(*this, obj);
+ set<Slot>::iterator i = objects.find(slot);
if(i==objects.end())
{
- i = objects.insert(SlotMap::value_type(&obj, Slot(&obj))).first;
- i->second.evch_conn = obj.signal_events_changed.connect(sigc::bind(sigc::mem_fun(this, &EventDispatcher::object_events_changed), &obj));
- i->second.del_conn = obj.signal_deleted.connect(sigc::bind(sigc::mem_fun(this, &EventDispatcher::object_deleted), &obj));
+ i = objects.insert(slot).first;
+ i->connect_signals();
if(obj.get_events())
poller.set_object(obj, obj.get_events());
void EventDispatcher::remove(EventObject &obj)
{
- SlotMap::iterator i = objects.find(&obj);
+ set<Slot>::iterator i = objects.find(Slot(*this, obj));
if(i!=objects.end())
{
- i->second.evch_conn.disconnect();
- i->second.del_conn.disconnect();
objects.erase(i);
poller.set_object(obj, P_NONE);
tick();
}
-void EventDispatcher::object_events_changed(PollEvent ev, EventObject *obj)
+void EventDispatcher::dispatch()
{
- poller.set_object(*obj, ev);
+ const Poller::SlotList &result = poller.get_result();
+ for(Poller::SlotList::const_iterator i=result.begin(); i!=result.end(); ++i)
+ i->object->event(i->events);
}
-void EventDispatcher::object_deleted(EventObject *obj)
+
+EventDispatcher::Slot::Slot(EventDispatcher &d, EventObject &o):
+ disp(d),
+ obj(o)
+{ }
+
+void EventDispatcher::Slot::connect_signals() const
{
- remove(*obj);
+ obj.signal_events_changed.connect(sigc::mem_fun(this, &Slot::events_changed));
+ obj.signal_deleted.connect(sigc::mem_fun(this, &Slot::deleted));
}
-void EventDispatcher::dispatch()
+void EventDispatcher::Slot::events_changed(PollEvent ev) const
{
- const Poller::SlotList &result = poller.get_result();
- for(Poller::SlotList::const_iterator i=result.begin(); i!=result.end(); ++i)
- i->object->event(i->events);
+ disp.poller.set_object(obj, ev);
+}
+
+void EventDispatcher::Slot::deleted() const
+{
+ disp.remove(obj);
}
} // namespace IO
#ifndef MSP_IO_EVENTDISPATCHER_H_
#define MSP_IO_EVENTDISPATCHER_H_
-#include <sigc++/connection.h>
+#include <set>
#include <sigc++/trackable.h>
#include <msp/time/timedelta.h>
#include <msp/time/timer.h>
Put your I/O objects inside one of these to get signaled when something happens
on some of them.
*/
-class EventDispatcher: public sigc::trackable
+class EventDispatcher
{
private:
- struct Slot
+ struct Slot: public sigc::trackable
{
- EventObject *obj;
- sigc::connection evch_conn;
- sigc::connection del_conn;
+ EventDispatcher &disp;
+ EventObject &obj;
- Slot(EventObject *o): obj(o) { }
- };
+ Slot(EventDispatcher &, EventObject &);
+
+ void connect_signals() const;
+ void events_changed(PollEvent) const;
+ void deleted() const;
- typedef std::map<EventObject *, Slot> SlotMap;
+ bool operator<(const Slot &o) const { return &obj<&o.obj; }
+ };
Poller poller;
- SlotMap objects;
+ std::set<Slot> objects;
public:
- EventDispatcher();
- ~EventDispatcher();
-
void add(EventObject &);
void remove(EventObject &);
void tick(const Time::Timer &);
private:
- void object_events_changed(PollEvent, EventObject *);
- void object_deleted(EventObject *);
void dispatch();
};