MobiusCore/Source/EffectHandlers/ThreadSafeConnectable.swift (51 lines of code) (raw):

// Copyright Spotify AB. // SPDX-License-Identifier: Apache-2.0 final class ThreadSafeConnectable<Event, Effect>: Connectable { private let connectable: AnyConnectable<Effect, Event> private let lock = Lock() private var output: Consumer<Event>? private var connection: Connection<Effect>? init<Conn: Connectable>( connectable: Conn ) where Conn.Input == Effect, Conn.Output == Event { self.connectable = AnyConnectable(connectable) } func connect(_ output: @escaping (Event) -> Void) -> Connection<Effect> { return lock.synchronized { guard self.output == nil, connection == nil else { MobiusHooks.errorHandler( "Connection limit exceeded: The Connectable \(type(of: self)) is already connected. " + "Unable to connect more than once", #file, #line ) } self.output = output connection = connectable.connect(self.dispatch) return Connection( acceptClosure: accept, disposeClosure: dispose ) } } private func accept(_ effect: Effect) { if let connection = lock.synchronized(closure: { connection }) { connection.accept(effect) } } private func dispatch(event: Event) { if let output = lock.synchronized(closure: { output }) { output(event) } } private func dispose() { var disposeConnection: (() -> Void)? lock.synchronized { output = nil disposeConnection = connection?.dispose connection = nil } disposeConnection?() } deinit { dispose() } }