diff options
Diffstat (limited to 'Swiften/EventLoop/EventLoop.cpp')
-rw-r--r-- | Swiften/EventLoop/EventLoop.cpp | 133 |
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; + }); } } |