summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2015-11-18 13:51:58 (GMT)
committerSwift Review <review@swift.im>2015-11-19 15:32:04 (GMT)
commitfcf6a898de9c4f89db5de686aa203b3a52c18029 (patch)
tree4df426d92600eba8d4d60a88faaff1d5839129b0 /Swiften/EventLoop/Cocoa
parentcda6fd478b3d8f7f30f771b18324db389a01b1b3 (diff)
downloadswift-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/Cocoa')
-rw-r--r--Swiften/EventLoop/Cocoa/CocoaEvent.h4
-rw-r--r--Swiften/EventLoop/Cocoa/CocoaEvent.mm13
-rw-r--r--Swiften/EventLoop/Cocoa/CocoaEventLoop.h14
-rw-r--r--Swiften/EventLoop/Cocoa/CocoaEventLoop.mm34
4 files changed, 48 insertions, 17 deletions
diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.h b/Swiften/EventLoop/Cocoa/CocoaEvent.h
index dc38f7f..4453c74 100644
--- a/Swiften/EventLoop/Cocoa/CocoaEvent.h
+++ b/Swiften/EventLoop/Cocoa/CocoaEvent.h
@@ -9,7 +9,6 @@
#include <Foundation/Foundation.h>
namespace Swift {
- class Event;
class CocoaEventLoop;
}
@@ -19,14 +18,13 @@ namespace Swift {
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
@interface CocoaEvent : NSObject {
- Swift::Event* event;
Swift::CocoaEventLoop* eventLoop;
}
#pragma clang diagnostic pop
// Takes ownership of event
-- (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el;
+- (id) init:(Swift::CocoaEventLoop*) el;
- (void) process;
- (void) dealloc;
diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.mm b/Swiften/EventLoop/Cocoa/CocoaEvent.mm
index 7b1b4b0..4f72c29 100644
--- a/Swiften/EventLoop/Cocoa/CocoaEvent.mm
+++ b/Swiften/EventLoop/Cocoa/CocoaEvent.mm
@@ -1,24 +1,27 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <Swiften/EventLoop/Cocoa/CocoaEvent.h>
-#include <Swiften/EventLoop/Event.h>
#include <Swiften/EventLoop/Cocoa/CocoaEventLoop.h>
@implementation CocoaEvent
-- (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el {
+- (id) init:(Swift::CocoaEventLoop*) el {
self = [super init];
if (self != nil) {
- event = e;
eventLoop = el;
}
return self;
}
- (void) process {
- eventLoop->handleEvent(*event);
+ eventLoop->handleNextCocoaEvent();
}
- (void) dealloc {
- delete event;
[super dealloc];
}
diff --git a/Swiften/EventLoop/Cocoa/CocoaEventLoop.h b/Swiften/EventLoop/Cocoa/CocoaEventLoop.h
index ee33fbb..aad6b0a 100644
--- a/Swiften/EventLoop/Cocoa/CocoaEventLoop.h
+++ b/Swiften/EventLoop/Cocoa/CocoaEventLoop.h
@@ -1,20 +1,28 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
+#include <boost/thread.hpp>
+
#include <Swiften/EventLoop/EventLoop.h>
namespace Swift {
class CocoaEventLoop : public EventLoop {
public:
CocoaEventLoop();
+ virtual ~CocoaEventLoop();
- virtual void post(const Event& event);
+ void handleNextCocoaEvent();
+
+ protected:
+ virtual void eventPosted();
- using EventLoop::handleEvent;
+ private:
+ bool isEventInCocoaEventLoop_;
+ boost::recursive_mutex isEventInCocoaEventLoopMutex_;
};
}
diff --git a/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm b/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm
index ba73884..88da262 100644
--- a/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm
+++ b/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <Swiften/EventLoop/Cocoa/CocoaEventLoop.h>
#include <Swiften/EventLoop/Cocoa/CocoaEvent.h>
@@ -5,17 +11,33 @@
namespace Swift {
-CocoaEventLoop::CocoaEventLoop() {
+CocoaEventLoop::CocoaEventLoop() : isEventInCocoaEventLoop_(false) {
+}
+
+CocoaEventLoop::~CocoaEventLoop() {
+
+}
+
+void CocoaEventLoop::handleNextCocoaEvent() {
+ {
+ boost::recursive_mutex::scoped_lock lock(isEventInCocoaEventLoopMutex_);
+ isEventInCocoaEventLoop_ = false;
+ }
+ handleNextEvent();
}
-void CocoaEventLoop::post(const Event& event) {
- Event* eventCopy = new Event(event);
- CocoaEvent* cocoaEvent = [[CocoaEvent alloc] initWithEvent: eventCopy eventLoop: this];
- [cocoaEvent
+void CocoaEventLoop::eventPosted() {
+ boost::recursive_mutex::scoped_lock lock(isEventInCocoaEventLoopMutex_);
+ if (!isEventInCocoaEventLoop_) {
+ isEventInCocoaEventLoop_ = true;
+
+ CocoaEvent* cocoaEvent = [[CocoaEvent alloc] init: this];
+ [cocoaEvent
performSelectorOnMainThread:@selector(process)
withObject: nil
waitUntilDone: NO];
- [cocoaEvent release];
+ [cocoaEvent release];
+ }
}
}