Browse Source

Require a lock to access the connectivity state delegate (#634)

Motivation:

- It was not possible to update the connectivity delegate in a thread
  safe way.
- See #622

Modifications:

Require the state lock to get/set the connectivity state delegate.

Result:

TSAN is happy.
George Barnett 6 years ago
parent
commit
062b341d63
1 changed files with 17 additions and 5 deletions
  1. 17 5
      Sources/GRPC/ConnectivityState.swift

+ 17 - 5
Sources/GRPC/ConnectivityState.swift

@@ -55,19 +55,17 @@ public protocol ConnectivityStateDelegate: class {
 }
 
 public class ConnectivityStateMonitor {
-  /// A delegate to call when the connectivity state changes.
-  public var delegate: ConnectivityStateDelegate?
-
   private let logger = Logger(subsystem: .connectivityState)
   private let lock = Lock()
   private var _state: ConnectivityState = .idle
   private var _userInitiatedShutdown = false
+  private var _delegate: ConnectivityStateDelegate?
 
   /// Creates a new connectivity state monitor.
   ///
   /// - Parameter delegate: A delegate to call when the connectivity state changes.
   public init(delegate: ConnectivityStateDelegate?) {
-    self.delegate = delegate
+    self._delegate = delegate
   }
 
   /// The current state of connectivity.
@@ -84,6 +82,20 @@ public class ConnectivityStateMonitor {
     }
   }
 
+  /// A delegate to call when the connectivity state changes.
+  public var delegate: ConnectivityStateDelegate? {
+    get {
+      return self.lock.withLock {
+        return self._delegate
+      }
+    }
+    set {
+      self.lock.withLockVoid {
+        self._delegate = newValue
+      }
+    }
+  }
+
   /// Updates `_state` to `newValue`.
   ///
   /// If the user has initiated shutdown then state updates are _ignored_. This may happen if the
@@ -100,7 +112,7 @@ public class ConnectivityStateMonitor {
     if oldValue != newValue {
       self.logger.info("connectivity state change: \(oldValue) to \(newValue)")
       self._state = newValue
-      self.delegate?.connectivityStateDidChange(from: oldValue, to: newValue)
+      self._delegate?.connectivityStateDidChange(from: oldValue, to: newValue)
     }
   }