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
Deferred.swift:16
private struct DispatchBlockMarker: 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
MemoStore.swift:104
            atomicInitialize(boxPtr, to: .init(value))
<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:65
    private typealias Element = Box<Value>?
MemoStore.swift:72
                boxPtr.initialize(value.map(Box.init))
<T
MemoStore.swift:51
    let contents: T
MemoStore.swift:53
    init(_ contents: T) {
> { 0051 let contents
MemoStore.swift:54
        self.contents = contents
MemoStore.swift:98
            body(box.contents)
: T 0052 0053 init
MemoStore.swift:72
                boxPtr.initialize(value.map(Box.init))
MemoStore.swift:104
            atomicInitialize(boxPtr, to: .init(value))
(_ 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
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> {
<Value
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 {
> { 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:69
        let ptr = Manager(bufferClass: self, minimumCapacity: 1) { buffer, _ in
MemoStore.swift:71
            Manager(unsafeBufferObject: buffer).withUnsafeMutablePointerToElements { boxPtr in
MemoStore.swift:85
        return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements(body)
= ManagedBufferPointer<Void, Element> 0065 private typealias Element
MemoStore.swift:64
    private typealias Manager = ManagedBufferPointer<Void, Element>
MemoStore.swift:84
    private func withUnsafeMutablePointer<Return>(body: UnsafeMutablePointer<Element> -> Return) -> Return {
= Box<Value>? 0066 0067 static func createWithValue
Deferred.swift:48
        storage = MemoStore.createWithValue(nil)
Deferred.swift:53
        storage = MemoStore.createWithValue(value)
(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
MemoStore.swift:90
        withUnsafeMutablePointer { boxPtr in
MemoStore.swift:96
        withUnsafeMutablePointer { boxPtr in
MemoStore.swift:103
        return withUnsafeMutablePointer { boxPtr in
<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
Deferred.swift:63
            storage.withValue(body)
Deferred.swift:105
            storage.withValue(assign)
(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:129
        let wasFilled = storage.fill(value)
(value: Value) -> Bool { 0103 return withUnsafeMutablePointer { boxPtr in 0104 atomicInitialize(boxPtr, to: .init(value)) 0105 } 0106 } 0107 } 0108