 
 public final class MQTTClient {
     private let mosquittoContext: __MosquittoContext
-    internal let operationQueue: NSOperationQueue
-    public private(set) var isFinished: Bool
+    public private(set) var isFinished: Bool = false
+    internal let serialQueue: NSOperationQueue = {
+        let queue = NSOperationQueue()
+        queue.name = "MQTT Client Operation Queue"
+        queue.maxConcurrentOperationCount = 1
+        queue.suspended = true
+        return queue
+    }()
     public var isConnected: Bool {
         return mosquittoContext.isConnected
     }
 
     internal init(mosquittoContext: __MosquittoContext) {
         self.mosquittoContext = mosquittoContext
-        self.operationQueue = NSOperationQueue()
-        self.isFinished = false
-        
-        self.operationQueue.name = "MQTT Client Operation Queue"
-        self.operationQueue.suspended = true
     }
     
     deinit {
         disconnect()
     }
 
-    public func publish(payload: NSData, topic: String, qos: Int32, retain: Bool, requestCompletion: ((Mosq_Return, Int) -> Void)? = nil) {
-        synchronized { mosquittoContext, operationQueue in
-            operationQueue.addOperationWithBlock {
+    public func publish(payload: NSData, topic: String, qos: Int32, retain: Bool, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
+        serialQueue.addOperationWithBlock {
+            if (!self.isFinished) {
                 var messageId: Int32 = 0
-                let mosqReturn = mosquitto_publish(mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray,
-                                                   Int32(payload.length), payload.bytes, qos, retain)
-                requestCompletion?(Mosq_Return(rawValue: Int(mosqReturn))!, Int(messageId))
+                let mosqReturn = mosquitto_publish(self.mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray,
+                    Int32(payload.length), payload.bytes, qos, retain)
+                requestCompletion?(MosqResult(rawValue: Int(mosqReturn))!, Int(messageId))
             }
         }
     }
 
-    public func publishString(payload: String, topic: String, qos: Int32, retain: Bool, requestCompletion: ((Mosq_Return, Int) -> Void)? = nil) {
+    public func publishString(payload: String, topic: String, qos: Int32, retain: Bool, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
         if let payloadData = (payload as NSString).dataUsingEncoding(NSUTF8StringEncoding) {
-            self.publish(payloadData, topic: topic, qos: qos, retain: retain, requestCompletion)
-        }
-    }
-
-    public func subscribe(topic: String, qos: Int32, requestCompletion: ((Mosq_Return, Int) -> Void)? = nil) {
-        synchronized { mosquittoContext, operationQueue in
-            operationQueue.addOperationWithBlock {
+            publish(payloadData, topic: topic, qos: qos, retain: retain, requestCompletion)
+        }
+    }
+
+    public func subscribe(topic: String, qos: Int32, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
+        serialQueue.addOperationWithBlock {
+            if (!self.isFinished) {
                 var messageId: Int32 = 0
-                let mosqReturn = mosquitto_subscribe(mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray, qos)
-                requestCompletion?(Mosq_Return(rawValue: Int(mosqReturn))!, Int(messageId))
+                let mosqReturn = mosquitto_subscribe(self.mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray, qos)
+                requestCompletion?(MosqResult(rawValue: Int(mosqReturn))!, Int(messageId))
             }
         }
     }
 
-    public func unsubscribe(topic: String, requestCompletion: ((Mosq_Return, Int) -> Void)? = nil) {
-        synchronized { mosquittoContext, operationQueue in
-            operationQueue.addOperationWithBlock {
+    public func unsubscribe(topic: String, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
+        serialQueue.addOperationWithBlock {
+            if (!self.isFinished) {
                 var messageId: Int32 = 0
-                let mosqReturn = mosquitto_unsubscribe(mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray)
-                requestCompletion?(Mosq_Return(rawValue: Int(mosqReturn))!, Int(messageId))
+                let mosqReturn = mosquitto_unsubscribe(self.mosquittoContext.mosquittoHandler, &messageId, topic.cCharArray)
+                requestCompletion?(MosqResult(rawValue: Int(mosqReturn))!, Int(messageId))
             }
         }
     }
 
     public func disconnect() {
-        synchronized { mosquittoContext, operationQueue in
-            self.isFinished = true
-            operationQueue.addOperationWithBlock {
-                mosquitto_disconnect(mosquittoContext.mosquittoHandler)
-                return
+        if (!isFinished) {
+            isFinished = true
+            let context = mosquittoContext
+            serialQueue.addOperationWithBlock {
+                mosquitto_disconnect(context.mosquittoHandler)
+                mosquitto_loop_stop(context.mosquittoHandler, false)
+                mosquitto_context_cleanup(context)
             }
-            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
-                operationQueue.waitUntilAllOperationsAreFinished()
-                mosquitto_loop_stop(mosquittoContext.mosquittoHandler, false)
-                mosquitto_context_cleanup(mosquittoContext)
-            }
         }
     }
 
     public func awaitRequestCompletion() {
-        operationQueue.waitUntilAllOperationsAreFinished()
-    }
-
-    private func synchronized(operation: (__MosquittoContext, NSOperationQueue) -> Void) {
-        objc_sync_enter(self)
-        if (!isFinished) {
-            operation(self.mosquittoContext, self.operationQueue)
-        }
-        objc_sync_exit(self)
+        serialQueue.waitUntilAllOperationsAreFinished()
     }
 
     public var socket: Int32? {

    public var mqttClientCert: MQTTClientCert?
    public var mqttTlsOpts: MQTTTlsOpts?
    
    public var onConnectCallback: ((returnCode: ReturnCode) -> Void)?
    public var onDisconnectCallback: ((reasonCode: ReasonCode) -> Void)!
    public var onPublishCallback: ((messageId: Int) -> Void)!
    public var onMessageCallback: ((mqttMessage: MQTTMessage) -> Void)!
    public var onSubscribeCallback: ((messageId: Int, grantedQos: Array<Int32>) -> Void)!
    public var onUnsubscribeCallback: ((messageId: Int) -> Void)!
    
    public init(clientId: String, host: String, port: Int32, keepAlive: Int32) {
        // MQTT client ID is restricted to 23 characters in the MQTT v3.1 spec

    }
}

public enum MosqResult: Int {
    case MOSQ_CONN_PENDING = -1
    case MOSQ_SUCCESS = 0
    case MOSQ_NOMEM = 1
