我正在开发一个显着多线程的程序。我需要响应对象和线程之间的事件,所以我提出了以下代码。
#ifndef EVENT_H
#define EVENT_H
#include <vector>
#include <mutex>
#include <algorithm>
#include <memory>
/**
* Create the definition of a dispatcher for the event type (t)
*/
#define DISPATCHER(t) EventDispatcher<t>
/**
* Create the definition of a listener for event type (t)
*/
#define LISTENER(t) DISPATCHER(t)::EventListener
/**
* Dispatch a event (e) of type (t)
*/
#define DISPATCH(t, e) DISPATCHER(t)::dispatch(e);
/**
* Attach a listener (l) of type (t) to the dispatcher (d)
*/
#define LISTEN(t, d, l) ((DISPATCHER(t) *)(d))->addListener((l));
template <typename T>
class EventDispatcher {
public:
virtual ~EventDispatcher() {
std::unique_lock<std::recursive_mutex> uLock(lock);
// Prevent more listeners from being added.
isAlive = false;
// Remove all listeners.
while (listeners.begin() != listeners.end()) {
EventDispatcher<T>::EventListener *listener = *listeners.begin();
// Call remove listener so that the listener will be notified of the change.
removeListener(listener);
}
}
class EventListener {
friend EventDispatcher<T>;
public:
virtual ~EventListener() {
std::unique_lock<std::recursive_mutex> uLock(lock);
// Stop more dispatchers from connecting.
isAlive = false;
// Remove self from all dispatchers.
// Use while loop as removeListener will call removeDispatcher and modify dispatchers.
while (dispatchers.begin() != dispatchers.end()) {
EventDispatcher<T> *dispatcher = *dispatchers.begin();
dispatcher->removeListener(this);
}
}
protected:
/**
* Respond to an event.
* @param sender The dispatcher that sent the event.
* @param event The event that occurred.
*/
virtual void onEvent(EventDispatcher<T> *sender, std::shared_ptr<T> event) = 0;
private:
bool isAlive = true;
typedef std::vector<EventDispatcher<T> *> DispatcherList;
DispatcherList dispatchers;
std::recursive_mutex lock;
/**
* Add a reference to the dispatchers this listener is attached to.
* @param dispatcher The dispatcher that attached this listener.
* @return true if the listener is still alive.
*/
bool addDispatcher(EventDispatcher<T> *dispatcher) {
if (dispatcher == NULL) {
return false;
}
std::unique_lock<std::recursive_mutex> uLock(lock);
if (isAlive) {
if (std::find(dispatchers.begin(), dispatchers.end(), dispatcher) == dispatchers.end()) {
// This should only ever be called by the dispatcher so no need to call addListener.
dispatchers.push_back(dispatcher);
}
}
return isAlive;
}
/**
* Remove a reference to the dispatchers this listener is attached to.
* @param dispatcher The dispatcher that removed this listener.
*/
void removeDispatcher(EventDispatcher<T> *dispatcher) {
if (dispatcher == NULL) {
return;
}
std::unique_lock<std::recursive_mutex> uLock(lock);
typename DispatcherList::iterator itr = std::find(dispatchers.begin(), dispatchers.end(), dispatcher);
if (itr != dispatchers.end()) {
// This should only ever be called by the dispatcher so no need to call removeListener.
dispatchers.erase(itr);
}
}
};
public:
/**
* Add a listener to the dispatcher.
* @param listener The listener to add.
*/
void addListener(EventDispatcher<T>::EventListener *listener) {
if (listener == NULL) {
return;
}
std::unique_lock<std::recursive_mutex> uLock(lock);
if (isAlive) {
if (std::find(listeners.begin(), listeners.end(), listener) == listeners.end()) {
// Listener not in list, add it.
if (listener->addDispatcher(this)) {
// The listener was still alive so register it.
listeners.push_back(listener);
}
}
}
}
/**
* Remove a listener from the dispatcher.
* @param listener The listener to remove.
*/
void removeListener(EventDispatcher<T>::EventListener *listener) {
if (listener == NULL) {
return;
}
std::unique_lock<std::recursive_mutex> uLock(lock);
typename ListenerList::iterator itr = std::find(listeners.begin(), listeners.end(), listener);
if (itr != listeners.end()) {
listener->removeDispatcher(this);
listeners.erase(itr);
}
}
protected:
/**
* Dispatch an event to all listeners.
* @param event The event to dispatch.
* @note If the event is modifiable then not all listeners will necessarily get the exact same message.
* @note The event will be deleted before the function returns.
*/
void dispatch(T *event) {
std::shared_ptr<T> evt(event);
std::unique_lock<std::recursive_mutex> uLock(lock);
for (typename ListenerList::iterator iter = listeners.begin(); iter != listeners.end(); iter++) {
(*iter)->onEvent(this, evt);
}
}
/**
* Dispatch an event to all listeners.
* @param event The event to dispatch.
* @note If the event is modifiable then not all listeners will necessarily get the exact same message.
*/
void dispatch(std::shared_ptr<T> event) {
std::unique_lock<std::recursive_mutex> uLock(lock);
for (typename ListenerList::iterator iter = listeners.begin(); iter != listeners.end(); iter++) {
(*iter)->onEvent(this, event);
}
}
private:
bool isAlive = true;
typedef std::vector<EventListener *> ListenerList;
ListenerList listeners;
std::recursive_mutex lock;
};
#endif /* EVENT_H */
这是我设置的一个简单测试(不是多线程的)
#include "include/Event.h"
#include <iostream>
class ActionEvent {
public:
ActionEvent(int id) : actionID(id) {
// actionID = id;
}
const int actionID;
};
class PropertyChangeEvent {
public:
int propertyID;
};
class testDispatcher : public DISPATCHER(ActionEvent), public DISPATCHER(PropertyChangeEvent) {
public:
void test() {
// dispatch(new ActionEvent(0)); // ambiguous function.
// dispatch(new PropertyChangeEvent()); // ambiguous function.
// EventDispatcher<ActionEvent>::dispatch(new ActionEvent(1)); // works but is long.
// EventDispatcher<ActionEvent>::dispatch(new ActionEvent(2)); // works but is long.
// EventDispatcher<PropertyChangeEvent>::dispatch(new PropertyChangeEvent()); // works but is long.
DISPATCH(ActionEvent, new ActionEvent(1)); // The dispatcher will make a shared pointer then delete the event.
DISPATCH(ActionEvent, std::shared_ptr<ActionEvent>(new ActionEvent(2)));
DISPATCH(PropertyChangeEvent, new PropertyChangeEvent());
}
};
class testListener :
public LISTENER(ActionEvent), public LISTENER(PropertyChangeEvent) {
int ID;
public:
testListener(testDispatcher *dispatcher, int id) {
ID = id;
// dispatcher->addListener(this); // ambiguous function.
// dispatcher->addListener((EventDispatcher<ActionEvent>::EventListener *) this); // ambiguous function.
// ((EventDispatcher<ActionEvent> *)dispatcher)->addListener(this); // works but is long.
LISTEN(ActionEvent, dispatcher, this);
if(id % 2) {
// Only respond to property change events on odd numbered listeners just to be different.
// dispatcher->addListener(this); // ambiguous function.
// ((EventDispatcher<PropertyChangeEvent> *)dispatcher)->addListener(this); // works but is long.
LISTEN(PropertyChangeEvent, dispatcher, this);
}
}
protected:
void onEvent(EventDispatcher<ActionEvent> *source, std::shared_ptr<ActionEvent> event) {
(void)source;
(void)event;
std::cout << ID << " ActionEvent " << event->actionID << std::endl;
// event->actionID += 5;
// std::cout << " set to " << event->actionID << std::endl;
}
void onEvent(EventDispatcher<PropertyChangeEvent> *source, std::shared_ptr<PropertyChangeEvent> event) {
(void)source;
(void)event;
std::cout << ID << "PropertyChangeEvent" << std::endl;
}
};
int main(int argc, char *argv[]) {
testDispatcher td();
testListener tl1(&td, 1);
testListener tl2(&td, 2);
testListener tl3(&td, 3);
testListener tl4(&td, 4);
td.test();
return 0;
}
我真的很喜欢这方面的反馈。 有什么方法可以改进它吗? 我可以使模板更容易使用吗? (更好的宏?) 他们错过了任何可能的陷阱吗?