99import Dispatch
1010
1111#if SWIFT_PACKAGE
12- import Atomics
12+ import Atomics
1313#elseif XCODE
14- import Deferred. Atomics
14+ import Deferred. Atomics
1515#endif
1616
1717/// A deferred is a value that may become determined (or "filled") at some point
@@ -40,7 +40,7 @@ public final class Deferred<Value>: FutureProtocol, PromiseProtocol {
4040 /// Creates an instance resolved with `value`.
4141 public init ( filledWith value: Value ) {
4242 storage. withUnsafeMutablePointerToElements { ( pointerToElement) in
43- pointerToElement. initialize ( to: Storage . box ( value) )
43+ pointerToElement. initialize ( to: Storage . convertToReference ( value) )
4444 }
4545 }
4646
@@ -55,7 +55,8 @@ public final class Deferred<Value>: FutureProtocol, PromiseProtocol {
5555 private func notify( flags: DispatchWorkItemFlags , upon queue: DispatchQueue , execute body: @escaping ( Value ) -> Void ) {
5656 group. notify ( flags: flags, queue: queue) { [ storage] in
5757 guard let ptr = storage. withAtomicPointerToElement ( { bnr_atomic_ptr_load ( $0, . none) } ) else { return }
58- body ( Storage . unbox ( from: ptr) )
58+ let reference = Unmanaged < AnyObject > . fromOpaque ( ptr) . takeUnretainedValue ( )
59+ body ( Storage . convertFromReference ( reference) )
5960 }
6061 }
6162
@@ -81,7 +82,8 @@ public final class Deferred<Value>: FutureProtocol, PromiseProtocol {
8182 guard case . success = group. wait ( timeout: time) ,
8283 let ptr = storage. withAtomicPointerToElement ( { bnr_atomic_ptr_load ( $0, . none) } ) else { return nil }
8384
84- return Storage . unbox ( from: ptr)
85+ let reference = Unmanaged < AnyObject > . fromOpaque ( ptr) . takeUnretainedValue ( )
86+ return Storage . convertFromReference ( reference)
8587 }
8688
8789 // MARK: PromiseProtocol
@@ -94,7 +96,7 @@ public final class Deferred<Value>: FutureProtocol, PromiseProtocol {
9496
9597 @discardableResult
9698 public func fill( with value: Value ) -> Bool {
97- let box = Storage . box ( value)
99+ let box = Unmanaged . passRetained ( Storage . convertToReference ( value) )
98100
99101 let wonRace = storage. withAtomicPointerToElement {
100102 bnr_atomic_ptr_compare_and_swap ( $0, nil , box. toOpaque ( ) , . thread)
@@ -110,29 +112,16 @@ public final class Deferred<Value>: FutureProtocol, PromiseProtocol {
110112 }
111113}
112114
113- #if swift(>=3.1) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
114- private typealias DeferredRaw < T> = Unmanaged < AnyObject >
115- #else
116- // In order to assign the value of a scalar in a Deferred using atomics, we must
117- // box it up into something word-sized. See `atomicInitialize` above.
118- private final class Box < T> {
119- let contents : T
115+ private final class DeferredStorage < Value> : ManagedBuffer < Void , AnyObject ? > {
120116
121- init ( _ contents : T ) {
122- self . contents = contents
117+ static func create ( ) -> DeferredStorage < Value > {
118+ return unsafeDowncast ( super . create ( minimumCapacity : 1 , makingHeaderWith : { _ in } ) , to : DeferredStorage < Value > . self )
123119 }
124- }
125-
126- private typealias DeferredRaw < T> = Unmanaged < Box < T > >
127- #endif
128-
129- private final class DeferredStorage < Value> : ManagedBuffer < Void , DeferredRaw < Value > ? > {
130120
131- typealias _Self = DeferredStorage < Value >
132- typealias Element = DeferredRaw < Value >
133-
134- static func create( ) -> _Self {
135- return unsafeDowncast ( super. create ( minimumCapacity: 1 , makingHeaderWith: { _ in } ) , to: _Self. self)
121+ deinit {
122+ _ = withUnsafeMutablePointers { ( _, pointerToReference) in
123+ pointerToReference. deinitialize ( count: 1 )
124+ }
136125 }
137126
138127 func withAtomicPointerToElement< Return> ( _ body: ( UnsafeMutablePointer < UnsafeAtomicRawPointer > ) throws -> Return ) rethrows -> Return {
@@ -141,28 +130,33 @@ private final class DeferredStorage<Value>: ManagedBuffer<Void, DeferredRaw<Valu
141130 }
142131 }
143132
144- deinit {
145- guard let ptr = withAtomicPointerToElement ( { bnr_atomic_ptr_load ( $0, . global) } ) else { return }
146- Element . fromOpaque ( ptr) . release ( )
147- }
148-
149- static func unbox( from ptr: UnsafeMutableRawPointer ) -> Value {
150- let raw = Element . fromOpaque ( ptr)
151- #if swift(>=3.1) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
133+ #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
134+ static func convertFromReference( _ value: AnyObject ) -> Value {
152135 // Contract of using box(_:) counterpart
153136 // swiftlint:disable:next force_cast
154- return raw. takeUnretainedValue ( ) as! Value
155- #else
156- return raw. takeUnretainedValue ( ) . contents
157- #endif
137+ return value as! Value
138+ }
139+
140+ static func convertToReference( _ value: Value ) -> AnyObject {
141+ return value as AnyObject
142+ }
143+ #else
144+ // In order to assign the value in a Deferred using atomics, we must
145+ // box it up into something word-sized. See `fill(with:)` above.
146+ private final class Box {
147+ let wrapped : Value
148+ init ( _ wrapped: Value ) {
149+ self . wrapped = wrapped
150+ }
151+ }
152+
153+ static func convertToReference( _ value: Value ) -> AnyObject {
154+ return Box ( value)
158155 }
159156
160- static func box( _ value: Value ) -> Element {
161- #if swift(>=3.1) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
162- return Unmanaged . passRetained ( value as AnyObject )
163- #else
164- return Unmanaged . passRetained ( Box ( value) )
165- #endif
157+ static func convertFromReference( _ value: AnyObject ) -> Value {
158+ return unsafeDowncast ( value, to: Box . self) . wrapped
166159 }
160+ #endif
167161
168162}
0 commit comments