/* * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include namespace Swift { inline void invokeCallback(const Event& event) { try { assert(!event.callback.empty()); event.callback(); } catch (const std::exception& e) { SWIFT_LOG(error) << "Uncaught exception in event loop: " << e.what() << std::endl; } catch (...) { SWIFT_LOG(error) << "Uncaught non-exception in event loop" << std::endl; } } EventLoop::EventLoop() : nextEventID_(0), handlingEvents_(false) { } EventLoop::~EventLoop() { } void EventLoop::handleNextEvents() { const int eventsBatched = 100; // If handleNextEvents 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 lock(removeEventsMutex_); { std::vector nextEvents; { std::unique_lock lock(eventsMutex_); for (int n = 0; ((n < eventsBatched) && !events_.empty()); n++) { nextEvents.push_back(events_.front()); events_.pop_front(); } callEventPosted = !events_.empty(); } if (!nextEvents.empty()) { for (const auto& event : nextEvents) { invokeCallback(event); } } } handlingEvents_ = false; } if (callEventPosted) { eventPosted(); } } void EventLoop::postEvent(boost::function callback, std::shared_ptr owner) { Event event(owner, callback); bool callEventPosted = false; { std::unique_lock lock(eventsMutex_); callEventPosted = events_.empty(); event.id = nextEventID_; nextEventID_++; events_.push_back(event); } if (callEventPosted) { eventPosted(); } } void EventLoop::removeEventsFromOwner(std::shared_ptr owner) { std::unique_lock removeLock(removeEventsMutex_, std::defer_lock); std::unique_lock eventsLock(eventsMutex_, std::defer_lock); std::lock(removeLock, eventsLock); events_.remove_if([&](const Event& event) { return event.owner == owner; }); } }