blob: 09a85e4860c9067965d8d877086b83250147e357 [file] [log] [blame]
// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_EVENT_
#define SHILL_EVENT_
#include <vector>
namespace shill {
// This is a pure-virtual base class for callback objects which can be
// queued up and called later. The callback virtual method takes a single
// argument, which will be handed to the dispatcher to call on all listeners.
template <typename Arg>
class Callback {
public:
virtual ~Callback() {}
virtual void Run(Arg arg) = 0;
};
// This is a callback subclass that contains an object and method to call.
// These methods take a passed-in argument specific to the callback type.
template <typename Class, typename Arg>
class ClassCallback : public Callback<Arg> {
public:
typedef void (Class::*MethodType)(Arg arg);
ClassCallback(Class* object, MethodType method)
: object_(object), method_(method) {}
~ClassCallback() {}
void Run(Arg arg) {
(object_->*method_)(arg);
}
private:
Class* object_;
MethodType method_;
};
// This is the event queue superclass, which contains a function for
// dispatching all events in the queue to their respective listeners.
// A common "AlertDispatcher()" function is used by subclasses to alert
// the central dispatcher that events have been queued and a dispatch
// should be performed soon.
class EventDispatcher;
class EventQueueItem {
public:
EventQueueItem(EventDispatcher *dispatcher);
~EventQueueItem();
virtual void Dispatch() = 0;
void AlertDispatcher();
private:
EventDispatcher *dispatcher_;
};
// This is a template subclass of EventQueueItem which is specific to
// a particular argument type. This object contains a queue of events
// waiting for delivery to liesteners, and a list of even callbacks --
// the listeners for this event.
template <typename Arg>
class EventQueue : public EventQueueItem {
typedef Callback<Arg>CallbackType;
public:
explicit EventQueue(EventDispatcher *dispatcher)
: EventQueueItem(dispatcher) {}
inline void AddCallback(CallbackType *cb) {
callback_list_.push_back(cb);
}
void RemoveCallback(CallbackType *cb) {
for (size_t event_idx = 0; event_idx < callback_list_.size(); ++event_idx) {
if (callback_list_[event_idx] == cb) {
callback_list_.erase(callback_list_.begin() + event_idx);
return;
}
}
}
void Dispatch() {
for (size_t event_idx = 0; event_idx < event_queue_.size(); ++event_idx)
for (size_t call_idx = 0; call_idx < callback_list_.size(); ++call_idx)
callback_list_[call_idx]->Run(event_queue_[event_idx]);
event_queue_.clear();
}
void AddEvent(Arg arg) {
event_queue_.push_back(arg);
AlertDispatcher();
}
private:
std::vector<CallbackType *> callback_list_;
std::vector<Arg> event_queue_;
};
// This is the main event dispatcher. It contains a central instance, and
// is the entity responsible for dispatching events out of all queues to
// their listeners during the idle loop.
class EventDispatcher {
public:
void DispatchEvents();
void ExecuteOnIdle();
void RegisterCallbackQueue(EventQueueItem *queue);
void UnregisterCallbackQueue(EventQueueItem *queue);
private:
std::vector<EventQueueItem*> queue_list_;
};
} // namespace shill
#endif // SHILL_EVENT_