@@ -40,64 +40,82 @@ extension UnsafeAtomicState where State == DisposableState {
4040
4141/// A type-erased disposable that forwards operations to an underlying disposable.
4242public final class AnyDisposable : Disposable {
43- private let disposable : Disposable
43+ private enum Backing {
44+ case wrapping( Disposable )
45+ case action( UnsafeAtomicState < DisposableState > , ( ( ) -> Void ) ? )
46+ }
47+
48+ private var base : Backing
4449
4550 public var isDisposed : Bool {
46- return disposable. isDisposed
51+ switch base {
52+ case let . action( state, _) :
53+ return state. is ( . disposed)
54+ case let . wrapping( disposable) :
55+ return disposable. isDisposed
56+ }
57+ }
58+
59+ /// Initialize the disposable to run the given action upon disposal.
60+ ///
61+ /// - parameters:
62+ /// - action: A closure to run when calling `dispose()`.
63+ public init ( _ action: @escaping ( ) -> Void ) {
64+ base = . action( UnsafeAtomicState ( DisposableState . active) , action)
4765 }
4866
4967 public init ( _ disposable: Disposable ) {
50- self . disposable = disposable
68+ base = . wrapping ( disposable)
5169 }
5270
53- public func dispose( ) {
54- disposable. dispose ( )
71+ public init ? ( _ disposable: Disposable ? ) {
72+ guard let disposable = disposable else {
73+ return nil
74+ }
75+ base = . wrapping( disposable)
5576 }
56- }
5777
58- /// A disposable that only flips `isDisposed` upon disposal, and performs no other
59- /// work.
60- public final class SimpleDisposable : Disposable {
61- private var state = UnsafeAtomicState ( DisposableState . active )
78+ deinit {
79+ switch base {
80+ case let . action ( state , _ ) :
81+ state. deinitialize ( )
6282
63- public var isDisposed : Bool {
64- return state. is ( . disposed)
83+ case . wrapping:
84+ break
85+ }
6586 }
6687
67- public init ( ) { }
68-
6988 public func dispose( ) {
70- _ = state. tryDispose ( )
71- }
89+ switch base {
90+ case let . action( state, action) :
91+ if state. tryDispose ( ) {
92+ assert ( action != nil , " Expected an action. Got none. " )
93+ action ? ( )
94+
95+ // The discriminator and the state pointer remains constant, and only the
96+ // optional closure reference is being overwritten with `nil`.
97+ base = . action( state, nil )
98+ }
7299
73- deinit {
74- state. deinitialize ( )
100+ case let . wrapping( disposable) :
101+ disposable. dispose ( )
102+ }
75103 }
76104}
77105
78- /// A disposable that will run an action upon disposal.
79- public final class ActionDisposable : Disposable {
80- private var action : ( ( ) -> Void ) ?
81- private var state : UnsafeAtomicState < DisposableState >
106+ /// A disposable that only flips `isDisposed` upon disposal, and performs no other
107+ /// work.
108+ public final class SimpleDisposable : Disposable {
109+ private var state = UnsafeAtomicState ( DisposableState . active )
82110
83111 public var isDisposed : Bool {
84112 return state. is ( . disposed)
85113 }
86114
87- /// Initialize the disposable to run the given action upon disposal.
88- ///
89- /// - parameters:
90- /// - action: A closure to run when calling `dispose()`.
91- public init ( action: @escaping ( ) -> Void ) {
92- self . action = action
93- self . state = UnsafeAtomicState ( DisposableState . active)
94- }
115+ public init ( ) { }
95116
96117 public func dispose( ) {
97- if state. tryDispose ( ) {
98- action ? ( )
99- action = nil
100- }
118+ _ = state. tryDispose ( )
101119 }
102120
103121 deinit {
@@ -179,7 +197,7 @@ public final class CompositeDisposable: Disposable {
179197 guard disposables != nil else { return nil }
180198
181199 let token = disposables!. insert ( d)
182- return ActionDisposable { [ weak self] in
200+ return AnyDisposable { [ weak self] in
183201 self ? . disposables. modify {
184202 $0? . remove ( using: token)
185203 }
@@ -197,12 +215,51 @@ public final class CompositeDisposable: Disposable {
197215 /// `disposable` is `nil`.
198216 @discardableResult
199217 public func add( _ action: @escaping ( ) -> Void ) -> Disposable ? {
200- return add ( ActionDisposable ( action : action) )
218+ return add ( AnyDisposable ( action) )
201219 }
202220
203221 deinit {
204222 state. deinitialize ( )
205223 }
224+
225+ /// Adds the right-hand-side disposable to the left-hand-side
226+ /// `CompositeDisposable`.
227+ ///
228+ /// ````
229+ /// disposable += producer
230+ /// .filter { ... }
231+ /// .map { ... }
232+ /// .start(observer)
233+ /// ````
234+ ///
235+ /// - parameters:
236+ /// - lhs: Disposable to add to.
237+ /// - rhs: Disposable to add.
238+ ///
239+ /// - returns: An instance of `DisposableHandle` that can be used to opaquely
240+ /// remove the disposable later (if desired).
241+ @discardableResult
242+ public static func += ( lhs: CompositeDisposable , rhs: Disposable ? ) -> Disposable ? {
243+ return lhs. add ( rhs)
244+ }
245+
246+ /// Adds the right-hand-side `ActionDisposable` to the left-hand-side
247+ /// `CompositeDisposable`.
248+ ///
249+ /// ````
250+ /// disposable += { ... }
251+ /// ````
252+ ///
253+ /// - parameters:
254+ /// - lhs: Disposable to add to.
255+ /// - rhs: Closure to add as a disposable.
256+ ///
257+ /// - returns: An instance of `DisposableHandle` that can be used to opaquely
258+ /// remove the disposable later (if desired).
259+ @discardableResult
260+ public static func += ( lhs: CompositeDisposable , rhs: @escaping ( ) -> ( ) ) -> Disposable ? {
261+ return lhs. add ( rhs)
262+ }
206263}
207264
208265/// A disposable that, upon deinitialization, will automatically dispose of
@@ -246,6 +303,44 @@ extension ScopedDisposable where Inner == AnyDisposable {
246303 }
247304}
248305
306+ extension ScopedDisposable where Inner == CompositeDisposable {
307+ /// Adds the right-hand-side disposable to the left-hand-side
308+ /// `ScopedDisposable<CompositeDisposable>`.
309+ ///
310+ /// ````
311+ /// disposable += { ... }
312+ /// ````
313+ ///
314+ /// - parameters:
315+ /// - lhs: Disposable to add to.
316+ /// - rhs: Disposable to add.
317+ ///
318+ /// - returns: An instance of `DisposableHandle` that can be used to opaquely
319+ /// remove the disposable later (if desired).
320+ @discardableResult
321+ public static func += ( lhs: ScopedDisposable < CompositeDisposable > , rhs: Disposable ? ) -> Disposable ? {
322+ return lhs. inner. add ( rhs)
323+ }
324+
325+ /// Adds the right-hand-side disposable to the left-hand-side
326+ /// `ScopedDisposable<CompositeDisposable>`.
327+ ///
328+ /// ````
329+ /// disposable += { ... }
330+ /// ````
331+ ///
332+ /// - parameters:
333+ /// - lhs: Disposable to add to.
334+ /// - rhs: Closure to add as a disposable.
335+ ///
336+ /// - returns: An instance of `DisposableHandle` that can be used to opaquely
337+ /// remove the disposable later (if desired).
338+ @discardableResult
339+ public static func += ( lhs: ScopedDisposable < CompositeDisposable > , rhs: @escaping ( ) -> ( ) ) -> Disposable ? {
340+ return lhs. inner. add ( rhs)
341+ }
342+ }
343+
249344/// A disposable that disposes of its wrapped disposable, and allows its
250345/// wrapped disposable to be replaced.
251346public final class SerialDisposable : Disposable {
@@ -293,78 +388,3 @@ public final class SerialDisposable: Disposable {
293388 state. deinitialize ( )
294389 }
295390}
296-
297- /// Adds the right-hand-side disposable to the left-hand-side
298- /// `CompositeDisposable`.
299- ///
300- /// ````
301- /// disposable += producer
302- /// .filter { ... }
303- /// .map { ... }
304- /// .start(observer)
305- /// ````
306- ///
307- /// - parameters:
308- /// - lhs: Disposable to add to.
309- /// - rhs: Disposable to add.
310- ///
311- /// - returns: An instance of `DisposableHandle` that can be used to opaquely
312- /// remove the disposable later (if desired).
313- @discardableResult
314- public func += ( lhs: CompositeDisposable , rhs: Disposable ? ) -> Disposable ? {
315- return lhs. add ( rhs)
316- }
317-
318- /// Adds the right-hand-side `ActionDisposable` to the left-hand-side
319- /// `CompositeDisposable`.
320- ///
321- /// ````
322- /// disposable += { ... }
323- /// ````
324- ///
325- /// - parameters:
326- /// - lhs: Disposable to add to.
327- /// - rhs: Closure to add as a disposable.
328- ///
329- /// - returns: An instance of `DisposableHandle` that can be used to opaquely
330- /// remove the disposable later (if desired).
331- @discardableResult
332- public func += ( lhs: CompositeDisposable , rhs: @escaping ( ) -> ( ) ) -> Disposable ? {
333- return lhs. add ( rhs)
334- }
335-
336- /// Adds the right-hand-side disposable to the left-hand-side
337- /// `ScopedDisposable<CompositeDisposable>`.
338- ///
339- /// ````
340- /// disposable += { ... }
341- /// ````
342- ///
343- /// - parameters:
344- /// - lhs: Disposable to add to.
345- /// - rhs: Disposable to add.
346- ///
347- /// - returns: An instance of `DisposableHandle` that can be used to opaquely
348- /// remove the disposable later (if desired).
349- @discardableResult
350- public func += ( lhs: ScopedDisposable < CompositeDisposable > , rhs: Disposable ? ) -> Disposable ? {
351- return lhs. inner. add ( rhs)
352- }
353-
354- /// Adds the right-hand-side disposable to the left-hand-side
355- /// `ScopedDisposable<CompositeDisposable>`.
356- ///
357- /// ````
358- /// disposable += { ... }
359- /// ````
360- ///
361- /// - parameters:
362- /// - lhs: Disposable to add to.
363- /// - rhs: Closure to add as a disposable.
364- ///
365- /// - returns: An instance of `DisposableHandle` that can be used to opaquely
366- /// remove the disposable later (if desired).
367- @discardableResult
368- public func += ( lhs: ScopedDisposable < CompositeDisposable > , rhs: @escaping ( ) -> ( ) ) -> Disposable ? {
369- return lhs. inner. add ( rhs)
370- }
0 commit comments