diff options
author | Tobias Markmann <tm@ayena.de> | 2015-11-18 13:51:58 (GMT) |
---|---|---|
committer | Swift Review <review@swift.im> | 2015-11-19 15:32:04 (GMT) |
commit | fcf6a898de9c4f89db5de686aa203b3a52c18029 (patch) | |
tree | 4df426d92600eba8d4d60a88faaff1d5839129b0 /Swiften/EventLoop/SingleThreadedEventLoop.cpp | |
parent | cda6fd478b3d8f7f30f771b18324db389a01b1b3 (diff) | |
download | swift-fcf6a898de9c4f89db5de686aa203b3a52c18029.zip swift-fcf6a898de9c4f89db5de686aa203b3a52c18029.tar.bz2 |
Redesign event loops to be thread-safe and deterministic
The new event loop design has a single event queue that is
synchronized to protect against data races.
The removal of events in the queue by EventOwner is
deterministic.
Test-Information:
All unit and integration tests with TSAN and
cxxflags=-DBOOST_SP_USE_PTHREADS on Debian 8.2 pass without
reports.
Multiple Swiften/QA/ClientTest/ClientTest runs under
different CPU stress caused no TSAN reports on Debian 8.2.
Swift itself only causes TSAN reports related to Qt itself,
out of our control, and most likely false positives, i.e.
TSAN not detecting the synchronization method inside Qt
correctly.
Unit tests pass without errors and successfully connected
to Slimber on OS X 10.10.5.
Change-Id: Ia1ed32ac2e758c5b9f86e0dac21362818740881e
Diffstat (limited to 'Swiften/EventLoop/SingleThreadedEventLoop.cpp')
-rw-r--r-- | Swiften/EventLoop/SingleThreadedEventLoop.cpp | 37 |
1 files changed, 14 insertions, 23 deletions
diff --git a/Swiften/EventLoop/SingleThreadedEventLoop.cpp b/Swiften/EventLoop/SingleThreadedEventLoop.cpp index c2235b1..095b962 100644 --- a/Swiften/EventLoop/SingleThreadedEventLoop.cpp +++ b/Swiften/EventLoop/SingleThreadedEventLoop.cpp @@ -12,54 +12,45 @@ #include "Swiften/Base/foreach.h" namespace Swift { SingleThreadedEventLoop::SingleThreadedEventLoop() -: shouldShutDown_(false) +: shouldShutDown_(false), eventAvailable_(false) { } SingleThreadedEventLoop::~SingleThreadedEventLoop() { - if (!events_.empty()) { - std::cerr << "Warning: Pending events in SingleThreadedEventLoop at destruction time." << std::endl; - } + } void SingleThreadedEventLoop::waitForEvents() { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - while (events_.empty() && !shouldShutDown_) { - eventsAvailable_.wait(lock); + boost::unique_lock<boost::mutex> lock(eventAvailableMutex_); + while (!eventAvailable_ && !shouldShutDown_) { + eventAvailableCondition_.wait(lock); } if (shouldShutDown_) throw EventLoopCanceledException(); } void SingleThreadedEventLoop::handleEvents() { - // Make a copy of the list of events so we don't block any threads that post - // events while we process them. - std::vector<Event> events; { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - events.swap(events_); - } - - // Loop through all the events and handle them - foreach(const Event& event, events) { - handleEvent(event); + boost::lock_guard<boost::mutex> lock(eventAvailableMutex_); + eventAvailable_ = false; } + handleNextEvent(); } void SingleThreadedEventLoop::stop() { - boost::unique_lock<boost::mutex> lock(eventsMutex_); + boost::unique_lock<boost::mutex> lock(eventAvailableMutex_); shouldShutDown_ = true; - eventsAvailable_.notify_one(); + eventAvailableCondition_.notify_one(); } -void SingleThreadedEventLoop::post(const Event& event) { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - events_.push_back(event); - eventsAvailable_.notify_one(); +void SingleThreadedEventLoop::eventPosted() { + boost::lock_guard<boost::mutex> lock(eventAvailableMutex_); + eventAvailable_ = true; + eventAvailableCondition_.notify_one(); } } // namespace Swift |