diff --git a/SSignalKit.xcodeproj/project.pbxproj b/SSignalKit.xcodeproj/project.pbxproj index 39fd44186c..9d389f62c6 100644 --- a/SSignalKit.xcodeproj/project.pbxproj +++ b/SSignalKit.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ D06F106C1A85561E00485185 /* SSignalBasicTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D06F106B1A85561E00485185 /* SSignalBasicTests.m */; }; D06F10711A855E2D00485185 /* DeallocatingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D06F10701A855E2D00485185 /* DeallocatingObject.m */; }; D06F10731A85882000485185 /* SSignalPerformanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D06F10721A85882000485185 /* SSignalPerformanceTests.m */; }; + D07A5CFD1BBDE6E400451791 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07A5CFC1BBDE6E400451791 /* Promise.swift */; }; D09FD73E1BA9BAB900FF0A4F /* SVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = D09FD73C1BA9BAB900FF0A4F /* SVariable.h */; settings = {ATTRIBUTES = (Public, ); }; }; D09FD73F1BA9BAB900FF0A4F /* SVariable.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FD73D1BA9BAB900FF0A4F /* SVariable.m */; }; /* End PBXBuildFile section */ @@ -199,6 +200,7 @@ D06F106F1A855E2D00485185 /* DeallocatingObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeallocatingObject.h; sourceTree = ""; }; D06F10701A855E2D00485185 /* DeallocatingObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeallocatingObject.m; sourceTree = ""; }; D06F10721A85882000485185 /* SSignalPerformanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSignalPerformanceTests.m; sourceTree = ""; }; + D07A5CFC1BBDE6E400451791 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = ""; }; D09FD73C1BA9BAB900FF0A4F /* SVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVariable.h; sourceTree = ""; }; D09FD73D1BA9BAB900FF0A4F /* SVariable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVariable.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -260,6 +262,7 @@ D0085B4C1B282BEE00EAF753 /* Disposable.swift */, D0085B4D1B282BEE00EAF753 /* Signal_Mapping.swift */, D0085B4E1B282BEE00EAF753 /* Subscriber.swift */, + D07A5CFC1BBDE6E400451791 /* Promise.swift */, D0085B261B282B9800EAF753 /* SwiftSignalKit.h */, D0085B241B282B9800EAF753 /* Supporting Files */, ); @@ -615,6 +618,7 @@ D0085B601B282BEE00EAF753 /* Disposable.swift in Sources */, D0085B531B282BEE00EAF753 /* ThreadPool.swift in Sources */, D0085B5F1B282BEE00EAF753 /* Signal.swift in Sources */, + D07A5CFD1BBDE6E400451791 /* Promise.swift in Sources */, D0085B5E1B282BEE00EAF753 /* Signal_Reduce.swift in Sources */, D0085B621B282BEE00EAF753 /* Subscriber.swift in Sources */, D0085B581B282BEE00EAF753 /* Signal_Take.swift in Sources */, diff --git a/SwiftSignalKit/Promise.swift b/SwiftSignalKit/Promise.swift new file mode 100644 index 0000000000..00e96b9649 --- /dev/null +++ b/SwiftSignalKit/Promise.swift @@ -0,0 +1,60 @@ +import Foundation + +public class Promise { + private var value: T? + private var lock: OSSpinLock = 0 + private let disposable = MetaDisposable() + private let subscribers = Bag Void>() + + public init(_ value: T) { + self.value = value + } + + public init() { + } + + deinit { + self.disposable.dispose() + } + + public func set(signal: Signal) { + OSSpinLockLock(&self.lock) + self.value = nil + OSSpinLockUnlock(&self.lock) + + self.disposable.set(signal.start(next: { [weak self] next in + if let strongSelf = self { + OSSpinLockLock(&strongSelf.lock) + strongSelf.value = next + let subscribers = strongSelf.subscribers.copyItems() + OSSpinLockUnlock(&strongSelf.lock); + + for subscriber in subscribers { + subscriber(next) + } + } + })) + } + + public func get() -> Signal { + return Signal { subscriber in + OSSpinLockLock(&self.lock) + let currentValue = self.value + let index = self.subscribers.add({ next in + subscriber.putNext(next) + }) + OSSpinLockUnlock(&self.lock) + + + if let currentValue = currentValue { + subscriber.putNext(currentValue) + } + + return ActionDisposable { + OSSpinLockLock(&self.lock) + self.subscribers.remove(index) + OSSpinLockUnlock(&self.lock) + } + } + } +} diff --git a/SwiftSignalKit/Queue.swift b/SwiftSignalKit/Queue.swift index fa46930ae6..178903b22d 100644 --- a/SwiftSignalKit/Queue.swift +++ b/SwiftSignalKit/Queue.swift @@ -3,6 +3,8 @@ import Foundation private let _QueueSpecificKey = NSObject() private let QueueSpecificKey: UnsafePointer = UnsafePointer(Unmanaged.passUnretained(_QueueSpecificKey).toOpaque()) +private let globalMainQueue = Queue(queue: dispatch_get_main_queue(), specialIsMainQueue: true) + public final class Queue { private let nativeQueue: dispatch_queue_t private var specific: UnsafeMutablePointer @@ -15,7 +17,7 @@ public final class Queue { } public class func mainQueue() -> Queue { - return Queue(queue: dispatch_get_main_queue(), specialIsMainQueue: true) + return globalMainQueue } public class func concurrentDefaultQueue() -> Queue {