0001 // 0002 // MemoStore.swift 0003 // Deferred 0004 // 0005 // Created by Zachary Waldowski on 12/8/15. 0006 // Copyright © 2014-2015 Big Nerd Ranch. Licensed under MIT. 0007 // 0008 0009 import Dispatch 0010 #if SWIFT_PACKAGE 0011 import AtomicSwift 0012 #endif 0013 0014 // Extremely simple surface describing an async rejoin-type notifier for a 0015 // one-off event. 0016 protocol CallbacksList{ 0017 init() 0018 0019 var isCompleted: Bool { get } 0020 0021 /// Unblock the waiter list. 0022 /// 0023 /// - precondition: `isCompleted` is false. 0024 /// - postcondition: `isCompleted` is true. 0025 func markCompleted() 0026 0027 /// Become notified when the list becomes unblocked. 0028 /// 0029 /// If `isCompleted`, an implementer should immediately submit the `body` 0030 /// to `queue`. 0031 func notify(upon queue: dispatch_queue_t, body: dispatch_block_t) 0032 } 0033 0034 // Atomic compare-and-swap, but safe for an initialize-once, owning pointer: 0035 // - ObjC: "MyObject *__strong *" 0036 // - Swift: "UnsafeMutablePointer<MyObject!>" 0037 // If the assignment is made, the new value is retained by its owning pointer. 0038 // If the assignment is not made, the new value is not retained. 0039 private func atomicInitialize
Deferred.swift:16 private struct DispatchBlockMarker: CallbacksList {<T: AnyObject>(target: UnsafeMutablePointer<T?>, to desired: T) -> Bool { 0040 let newPtr = Unmanaged.passRetained(desired).toOpaque() 0041 let wonRace = OSAtomicCompareAndSwapPtr(nil, UnsafeMutablePointer(newPtr), UnsafeMutablePointer(target)) 0042 if !wonRace { 0043 Unmanaged.passUnretained(desired).release() 0044 } 0045 return wonRace 0046 } 0047 0048 // In order to assign the value of a scalar in a Deferred using atomics, we must 0049 // box it up into something word-sized. See `atomicInitialize` above. 0050 private final class Box
MemoStore.swift:104 atomicInitialize(boxPtr, to: .init(value))<T
MemoStore.swift:65 private typealias Element = Box<Value>?MemoStore.swift:72 boxPtr.initialize(value.map(Box.init))> { 0051 let contents
MemoStore.swift:51 let contents: TMemoStore.swift:53 init(_ contents: T) {: T 0052 0053 init
MemoStore.swift:54 self.contents = contentsMemoStore.swift:98 body(box.contents)(_ contents: T) { 0054 self.contents = contents 0055 } 0056 } 0057 0058 // Heap storage that is initialized with a value once-and-only-once, atomically. 0059 final class MemoStore
MemoStore.swift:72 boxPtr.initialize(value.map(Box.init))MemoStore.swift:104 atomicInitialize(boxPtr, to: .init(value))<Value
Deferred.swift:43 private let storage: MemoStore<Value>Deferred.swift:48 storage = MemoStore.createWithValue(nil)Deferred.swift:53 storage = MemoStore.createWithValue(value)MemoStore.swift:67 static func createWithValue(value: Value?) -> MemoStore<Value> {> { 0060 // Using `ManagedBufferPointer` has advantages over a custom class: 0061 // - The data is efficiently stored in tail-allocated buffer space. 0062 // - The buffer has a stable pointer when locked to a single element. 0063 // - Better `holdsUniqueReference` support allows for future optimization. 0064 private typealias Manager
MemoStore.swift:65 private typealias Element = Box<Value>?MemoStore.swift:67 static func createWithValue(value: Value?) -> MemoStore<Value> {MemoStore.swift:67 static func createWithValue(value: Value?) -> MemoStore<Value> {MemoStore.swift:95 func withValue(body: Value -> Void) {MemoStore.swift:102 func fill(value: Value) -> Bool {= ManagedBufferPointer<Void, Element> 0065 private typealias Element
MemoStore.swift:69 let ptr = Manager(bufferClass: self, minimumCapacity: 1) { buffer, _ inMemoStore.swift:71 Manager(unsafeBufferObject: buffer).withUnsafeMutablePointerToElements { boxPtr inMemoStore.swift:85 return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements(body)= Box<Value>? 0066 0067 static func createWithValue
MemoStore.swift:64 private typealias Manager = ManagedBufferPointer<Void, Element>MemoStore.swift:84 private func withUnsafeMutablePointer<Return>(body: UnsafeMutablePointer<Element> -> Return) -> Return {(value: Value?) -> MemoStore<Value> { 0068 // Create storage. Swift uses a two-stage system. 0069 let ptr = Manager(bufferClass: self, minimumCapacity: 1) { buffer, _ in 0070 // Assign the initial value to managed storage 0071 Manager(unsafeBufferObject: buffer).withUnsafeMutablePointerToElements { boxPtr in 0072 boxPtr.initialize(value.map(Box.init)) 0073 } 0074 } 0075 0076 // Kindly give back an instance of the ManagedBufferPointer's buffer - self. 0077 return unsafeDowncast(ptr.buffer) 0078 } 0079 0080 private init() { 0081 fatalError("Unavailable method cannot be called") 0082 } 0083 0084 private func withUnsafeMutablePointer
Deferred.swift:48 storage = MemoStore.createWithValue(nil)Deferred.swift:53 storage = MemoStore.createWithValue(value)<Return>(body: UnsafeMutablePointer<Element> -> Return) -> Return { 0085 return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements(body) 0086 } 0087 0088 deinit { 0089 // UnsafeMutablePointer.destroy() is faster than destroy(_:) for single elements 0090 withUnsafeMutablePointer { boxPtr in 0091 boxPtr.destroy() 0092 } 0093 } 0094 0095 func withValue
MemoStore.swift:90 withUnsafeMutablePointer { boxPtr inMemoStore.swift:96 withUnsafeMutablePointer { boxPtr inMemoStore.swift:103 return withUnsafeMutablePointer { boxPtr in(body: Value -> Void) { 0096 withUnsafeMutablePointer { boxPtr in 0097 guard let box = boxPtr.memory else { return } 0098 body(box.contents) 0099 } 0100 } 0101 0102 func fill
Deferred.swift:63 storage.withValue(body)Deferred.swift:105 storage.withValue(assign)(value: Value) -> Bool { 0103 return withUnsafeMutablePointer { boxPtr in 0104 atomicInitialize(boxPtr, to: .init(value)) 0105 } 0106 } 0107 } 0108
Deferred.swift:129 let wasFilled = storage.fill(value)