summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/EventLoop/EventLoop.cpp')
-rw-r--r--Swiften/EventLoop/EventLoop.cpp133
1 files changed, 68 insertions, 65 deletions
diff --git a/Swiften/EventLoop/EventLoop.cpp b/Swiften/EventLoop/EventLoop.cpp
index 502bc49..1852f3f 100644
--- a/Swiften/EventLoop/EventLoop.cpp
+++ b/Swiften/EventLoop/EventLoop.cpp
@@ -1,36 +1,32 @@
/*
- * Copyright (c) 2010-2013 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
+ * Copyright (c) 2010-2019 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
*/
#include <Swiften/EventLoop/EventLoop.h>
#include <algorithm>
-#include <iostream>
#include <cassert>
-#include <boost/bind.hpp>
-#include <boost/lambda/lambda.hpp>
-#include <boost/lambda/bind.hpp>
-#include <boost/thread/locks.hpp>
+#include <vector>
-#include <Swiften/Base/Log.h>
+#include <boost/optional.hpp>
-namespace lambda = boost::lambda;
+#include <Swiften/Base/Log.h>
namespace Swift {
inline void invokeCallback(const Event& event) {
- try {
- assert(!event.callback.empty());
- event.callback();
- }
- catch (const std::exception& e) {
- std::cerr << "Uncaught exception in event loop: " << e.what() << std::endl;
- }
- catch (...) {
- std::cerr << "Uncaught non-exception in event loop" << std::endl;
- }
+ try {
+ assert(!event.callback.empty());
+ event.callback();
+ }
+ catch (const std::exception& e) {
+ SWIFT_LOG(error) << "Uncaught exception in event loop: " << e.what();
+ }
+ catch (...) {
+ SWIFT_LOG(error) << "Uncaught non-exception in event loop";
+ }
}
EventLoop::EventLoop() : nextEventID_(0), handlingEvents_(false) {
@@ -39,55 +35,62 @@ EventLoop::EventLoop() : nextEventID_(0), handlingEvents_(false) {
EventLoop::~EventLoop() {
}
-void EventLoop::handleEvent(const Event& event) {
- //SWIFT_LOG(debug) << "Handling event " << event.id << std::endl;
-
- if (handlingEvents_) {
- // We're being called recursively. Push in the list of events to
- // handle in the parent handleEvent()
- eventsToHandle_.push_back(event);
- return;
- }
-
- bool doCallback = false;
- {
- boost::lock_guard<boost::mutex> lock(eventsMutex_);
- std::list<Event>::iterator i = std::find(events_.begin(), events_.end(), event);
- if (i != events_.end()) {
- doCallback = true;
- events_.erase(i);
- }
- }
- if (doCallback) {
- handlingEvents_ = true;
- invokeCallback(event);
-
- // Process events that were passed to handleEvent during the callback
- // (i.e. through recursive calls of handleEvent)
- while (!eventsToHandle_.empty()) {
- Event nextEvent = eventsToHandle_.front();
- eventsToHandle_.pop_front();
- invokeCallback(nextEvent);
- }
- handlingEvents_ = false;
- }
+void EventLoop::handleNextEvent() {
+ // If handleNextEvent is already in progress, e.g. in case of a recursive call due to
+ // the event loop implementation, then do no handle further events. Instead call
+ // eventPosted() to continue event handling later.
+ bool callEventPosted = handlingEvents_;
+ if (!handlingEvents_) {
+ handlingEvents_ = true;
+ std::unique_lock<std::recursive_mutex> lock(removeEventsMutex_);
+ {
+ boost::optional<Event> nextEvent;
+ {
+ std::unique_lock<std::recursive_mutex> eventsLock(eventsMutex_);
+ if (!events_.empty()) {
+ nextEvent = events_.front();
+ events_.pop_front();
+ }
+ callEventPosted = !events_.empty();
+ }
+ if (nextEvent) {
+ invokeCallback(*nextEvent);
+ }
+ }
+ handlingEvents_ = false;
+ }
+
+ if (callEventPosted) {
+ eventPosted();
+ }
}
-void EventLoop::postEvent(boost::function<void ()> callback, boost::shared_ptr<EventOwner> owner) {
- Event event(owner, callback);
- {
- boost::lock_guard<boost::mutex> lock(eventsMutex_);
- event.id = nextEventID_;
- nextEventID_++;
- events_.push_back(event);
- }
- //SWIFT_LOG(debug) << "Posting event " << event.id << std::endl;
- post(event);
+void EventLoop::postEvent(boost::function<void ()> callback, std::shared_ptr<EventOwner> owner) {
+ Event event(owner, callback);
+ bool callEventPosted = false;
+ {
+ std::unique_lock<std::recursive_mutex> lock(eventsMutex_);
+
+ callEventPosted = events_.empty();
+
+ event.id = nextEventID_;
+ nextEventID_++;
+ events_.push_back(event);
+ }
+ if (callEventPosted) {
+ eventPosted();
+ }
}
-void EventLoop::removeEventsFromOwner(boost::shared_ptr<EventOwner> owner) {
- boost::lock_guard<boost::mutex> lock(eventsMutex_);
- events_.remove_if(lambda::bind(&Event::owner, lambda::_1) == owner);
+void EventLoop::removeEventsFromOwner(std::shared_ptr<EventOwner> owner) {
+ std::unique_lock<std::recursive_mutex> removeLock(removeEventsMutex_, std::defer_lock);
+ std::unique_lock<std::recursive_mutex> eventsLock(eventsMutex_, std::defer_lock);
+
+ std::lock(removeLock, eventsLock);
+
+ events_.remove_if([&](const Event& event) {
+ return event.owner == owner;
+ });
}
}