     // MARK: - Initialization
     
     public init(hostController: HostController,
-                options: GATTCentralOptions = GATTCentralOptions()) {
+                options: GATTCentralOptions = GATTCentralOptions(),
+                newConnection: NewConnection? = nil) {
         
         self.hostController = hostController
         self.options = options
+        self.newConnection = newConnection
     }
     
     // MARK: - Methods
     
-    public func scan(filterDuplicates: Bool = true,
-                     foundDevice: @escaping (ScanData<Peripheral, Advertisement>) -> ()) throws {
+    public func scan(filterDuplicates: Bool,
+                     _ foundDevice: @escaping (Result<ScanData<Peripheral, Advertisement>, Error>) -> ()) {
         
         precondition(isScanning == false, "Already scanning")
         
-        self.log?("Scanning...")
-        
-        self.isScanning = true
-        
-        do {
+        queue.async { [weak self] in
+            guard let self = self else { return }
+            self.log?("Scanning...")
+            self.isScanning = true
+            do {
+                try hostController.lowEnergyScan(filterDuplicates: filterDuplicates, parameters: options.scanParameters, shouldContinue: { [unowned self] in self.isScanning }) { [unowned self] (report) in
+                    
+                    let peripheral = Peripheral(identifier: report.address)
+                    let isConnectable = report.event.isConnectable
+                    let scanData = ScanData(
+                        peripheral: peripheral,
+                        date: Date(),
+                        rssi: Double(report.rssi.rawValue),
+                        advertisementData: report.responseData,
+                        isConnectable: isConnectable
+                    )
+                    self.scanData[peripheral] = (scanData, report)
+                    foundDevice(.success(scanData))
+                }
+            } catch {
+                self.isScanning = false
+                self.log?("Unable to scan: \(error)")
+            }
             
-            try hostController.lowEnergyScan(filterDuplicates: filterDuplicates, parameters: options.scanParameters, shouldContinue: { [unowned self] in self.isScanning }) { [unowned self] (report) in
-                
-                let peripheral = Peripheral(identifier: report.address)
-                
-                let isConnectable = report.event.isConnectable
-                
-                let scanData = ScanData(peripheral: peripheral,
-                                        date: Date(),
-                                        rssi: Double(report.rssi.rawValue),
-                                        advertisementData: report.responseData,
-                                        isConnectable: isConnectable)
-                
-                self.scanData[peripheral] = (scanData, report)
-                
-                foundDevice(scanData)
-            }
-        } catch {
-            self.isScanning = false
-            throw error
-        }
-        
-        self.log?("Did discover \(self.scanData.count) peripherals")
-        assert(isScanning == false, "Invalid scanning state: \(isScanning)")
+            self.log?("Did discover \(self.scanData.count) peripherals")
+            assert(isScanning == false, "Invalid scanning state: \(isScanning)")
+        }
     }
     
     public func stopScan() {

    // MARK: - Private Methods
    
    private func newConnectionID() -> Int {
        
        lastConnectionID += 1
        
        return lastConnectionID
    }
    

        
        guard let _ = scanData[peripheral]
            else { throw CentralError.unknownPeripheral }
        guard let connection = connections[peripheral]
            else { throw CentralError.disconnected }
        return connection
    }
    
    private func async<T>(timeout: TimeInterval,
                          completion: @escaping (Result<T, Error>) -> (),
                          _ block: @escaping (GATTCentral) throws -> (T),) {
        
        queue.async { [weak self] in
            let semaphore = Semaphore<T>(timeout: timeout)
            self?.concurrentQueue.async { [weak self] in
                guard let self = self else { return }
                do {
                    let value = try block(self)
                    semaphore.stopWaiting(.success(value))
                }
                catch { semaphore.stopWaiting(.failure(error)) }
            }
            let result = Result<T, Error>(catching: { try semaphore.wait() })
            completion(result)
        }
    }
}

