         }
     }
     
+    /// Modify the value of a characteristic, optionally emiting notifications if configured on active connections.
+    public func write(_ newValue: Data, forCharacteristic handle: UInt16) async {
+        await withUnsafeContinuation { [unowned self] (continuation: UnsafeContinuation<(), Never>) in
+            self.queue.async { [unowned self] in
+                // update GATT DB
+                database[characteristic: handle] = newValue
+                continuation.resume()
+            }
+        }
+        // send notifications
+        await notify(newValue, forCharacteristic: handle)
+    }
+    
     // MARK: Subscript
     
     public subscript(characteristic handle: UInt16) -> Data {
-        get { return database[characteristic: handle] }
-        set { writeValue(newValue, for: handle) }
+        return self.queue.sync { [unowned self] in
+            self.database[characteristic: handle]
+        }
     }
     
     // MARK: - Private Methods
     
-    private func writeValue(_ newValue: Data, for handle: UInt16) {
-        // update GATT DB
-        database[characteristic: handle] = newValue
-        let characteristicObject = database.characteristic(for: handle)
-        notify(newValue, for: characteristicObject)
-    }
-    
-    private func notify(_ value: Data, for characteristic: CBMutableCharacteristic) {
-        
-        // sends an updated characteristic value to one or more subscribed centrals, via a notification or indication.
-        let didNotify = peripheralManager.updateValue(
-            value,
-            for: characteristic,
-            onSubscribedCentrals: nil
-        )
-        
-        // The underlying transmit queue is full
-        if didNotify == false {
-            // send later in `peripheralManagerIsReady(toUpdateSubscribers:)` method is invoked
-            // when more space in the transmit queue becomes available.
-            notifyQueue.append((characteristic, value))
-            //log("Did queue notification for \((characteristic as CBCharacteristic).uuid)")
-        } else {
-            //log("Did send notification for \((characteristic as CBCharacteristic).uuid)")
+    private func notify(_ value: Data, forCharacteristic handle: UInt16) async {
+        
+        // attempt to write notifications
+        var didNotify = await updateValue(value, forCharacteristic: handle)
+        while didNotify == false {
+            await waitPeripheralReadyUpdateSubcribers()
+            didNotify = await updateValue(value, forCharacteristic: handle)
+        }
+    }
+    
+    private func waitPeripheralReadyUpdateSubcribers() async {
+        await withCheckedContinuation { [unowned self] continuation in
+            self.queue.async { [unowned self] in
+                self.continuation.canNotify = continuation
+            }
+        }
+    }
+    
+    private func updateValue(_ value: Data, forCharacteristic handle: UInt16) async -> Bool {
+        return await withUnsafeContinuation { [unowned self] continuation in
+            self.queue.async { [unowned self] in
+                let characteristicObject = database.characteristic(for: handle)
+                // sends an updated characteristic value to one or more subscribed centrals, via a notification or indication.
+                let didNotify = peripheralManager.updateValue(
+                    value,
+                    for: characteristicObject,
+                    onSubscribedCentrals: nil
+                )
+                
+                // The underlying transmit queue is full
+                if didNotify == false {
+                    // send later in `peripheralManagerIsReady(toUpdateSubscribers:)` method is invoked
+                    // when more space in the transmit queue becomes available.
+                    //log("Did queue notification for \((characteristic as CBCharacteristic).uuid)")
+                } else {
+                    //log("Did send notification for \((characteristic as CBCharacteristic).uuid)")
+                }
+                
+                continuation.resume(returning: didNotify)
+            }
         }
     }
 }

            return lastHandle
        }
        
        func add(service: GATTAttribute.Service, _ coreService: CBMutableService) -> UInt16 {
            
            let serviceHandle = newHandle()
            

            return serviceHandle
        }
        
        mutating func remove(service handle: UInt16) {
            
            let coreService = service(for: handle)
            
