Use a queue for events
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 25 Sep 2010 15:04:26 +0000 (17:04 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 13 Oct 2010 23:06:31 +0000 (01:06 +0200)
Using a queue ensures that events will be processed in order, i.e. if processing
an events generates new ones, those won't be handled before the first one is fully done.
We also let Qt process its own QEvents in between, in order to not block things like
network handling.

src/common/eventmanager.cpp
src/common/eventmanager.h

index 552765a..9664864 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "eventmanager.h"
 
+#include <QCoreApplication>
+#include <QEvent>
 #include <QDebug>
 
 #include "event.h"
@@ -28,6 +30,11 @@ EventManager::EventManager(QObject *parent) : QObject(parent) {
 
 }
 
+EventManager::~EventManager() {
+  // pending events won't be delivered anymore, but we do need to delete them
+  qDeleteAll(_eventQueue);
+}
+
 QMetaEnum EventManager::eventEnum() const {
   if(!_enum.isValid()) {
     int eventEnumIndex = metaObject()->indexOfEnumerator("EventType");
@@ -107,10 +114,31 @@ void EventManager::registerEventHandler(QList<EventType> events, QObject *object
 // not threadsafe! if we should want that, we need to add a mutexed queue somewhere in this general area.
 void EventManager::sendEvent(Event *event) {
   // qDebug() << "Sending" << event;
-  dispatchEvent(event);
+  _eventQueue.append(event);
+  if(_eventQueue.count() == 1) // we're not currently processing another event
+    processEvents();
+}
+
+void EventManager::customEvent(QEvent *event) {
+  if(event->type() == QEvent::User) {
+    processEvents();
+    event->accept();
+  }
+}
+
+void EventManager::processEvents() {
+  // we only process one event at a time for now, and let Qt's own event processing come in between
+  if(_eventQueue.isEmpty())
+    return;
+  dispatchEvent(_eventQueue.first());
+  _eventQueue.removeFirst();
+  if(_eventQueue.count())
+    QCoreApplication::postEvent(this, new QEvent(QEvent::User));
 }
 
 void EventManager::dispatchEvent(Event *event) {
+  //qDebug() << "Dispatching" << event;
+
   // we try handlers from specialized to generic by masking the enum
 
   // build a list sorted by priorities that contains all eligible handlers
index 73ff8b7..698b374 100644 (file)
@@ -101,7 +101,7 @@ public:
   };
 
   EventManager(QObject *parent = 0);
-  //virtual ~EventManager();
+  virtual ~EventManager();
 
   EventType eventTypeByName(const QString &name) const;
   EventType eventGroupByName(const QString &name) const;
@@ -120,6 +120,9 @@ public slots:
    */
   void sendEvent(Event *event);
 
+protected:
+  virtual void customEvent(QEvent *event);
+
 private:
   struct Handler {
     QObject *object;
@@ -141,6 +144,7 @@ private:
   //! Add handlers to an existing sorted (by priority) handler list
   void insertHandlers(const QList<Handler> &newHandlers, QList<Handler> &existing);
 
+  void processEvents();
   void dispatchEvent(Event *event);
 
   //! @return the EventType enum
@@ -148,6 +152,8 @@ private:
 
   HandlerHash _registeredHandlers;
   mutable QMetaEnum _enum;
+
+  QList<Event *> _eventQueue;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(EventManager::EventFlags);