mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Add 'submodules/SSignalKit/' from commit '359b2ee7c9f20f99f221f78e307369ef5ad0ece2'
git-subtree-dir: submodules/SSignalKit git-subtree-mainline:4459dc5b47git-subtree-split:359b2ee7c9
This commit is contained in:
43
submodules/SSignalKit/SwiftSignalKit/Atomic.swift
Normal file
43
submodules/SSignalKit/SwiftSignalKit/Atomic.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
import Foundation
|
||||
|
||||
public final class Atomic<T> {
|
||||
private var lock: pthread_mutex_t
|
||||
private var value: T
|
||||
|
||||
public init(value: T) {
|
||||
self.lock = pthread_mutex_t()
|
||||
self.value = value
|
||||
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func with<R>(_ f: (T) -> R) -> R {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
let result = f(self.value)
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public func modify(_ f: (T) -> T) -> T {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
let result = f(self.value)
|
||||
self.value = result
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public func swap(_ value: T) -> T {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
let previous = self.value
|
||||
self.value = value
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
return previous
|
||||
}
|
||||
}
|
||||
97
submodules/SSignalKit/SwiftSignalKit/Bag.swift
Normal file
97
submodules/SSignalKit/SwiftSignalKit/Bag.swift
Normal file
@@ -0,0 +1,97 @@
|
||||
import Foundation
|
||||
|
||||
public final class Bag<T> {
|
||||
public typealias Index = Int
|
||||
private var nextIndex: Index = 0
|
||||
private var items: [T] = []
|
||||
private var itemKeys: [Index] = []
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func add(_ item: T) -> Index {
|
||||
let key = self.nextIndex
|
||||
self.nextIndex += 1
|
||||
self.items.append(item)
|
||||
self.itemKeys.append(key)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
public func get(_ index: Index) -> T? {
|
||||
var i = 0
|
||||
for key in self.itemKeys {
|
||||
if key == index {
|
||||
return self.items[i]
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public func remove(_ index: Index) {
|
||||
var i = 0
|
||||
for key in self.itemKeys {
|
||||
if key == index {
|
||||
self.items.remove(at: i)
|
||||
self.itemKeys.remove(at: i)
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
public func removeAll() {
|
||||
self.items.removeAll()
|
||||
self.itemKeys.removeAll()
|
||||
}
|
||||
|
||||
public func copyItems() -> [T] {
|
||||
return self.items
|
||||
}
|
||||
|
||||
public func copyItemsWithIndices() -> [(Index, T)] {
|
||||
var result: [(Index, T)] = []
|
||||
var i = 0
|
||||
for key in self.itemKeys {
|
||||
result.append((key, self.items[i]))
|
||||
i += 1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public var isEmpty: Bool {
|
||||
return self.items.isEmpty
|
||||
}
|
||||
|
||||
public var first: (Index, T)? {
|
||||
if !self.items.isEmpty {
|
||||
return (self.itemKeys[0], self.items[0])
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class CounterBag {
|
||||
private var nextIndex: Int = 1
|
||||
private var items = Set<Int>()
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func add() -> Int {
|
||||
let index = self.nextIndex
|
||||
self.nextIndex += 1
|
||||
self.items.insert(index)
|
||||
return index
|
||||
}
|
||||
|
||||
public func remove(_ index: Int) {
|
||||
self.items.remove(index)
|
||||
}
|
||||
|
||||
public var isEmpty: Bool {
|
||||
return self.items.isEmpty
|
||||
}
|
||||
}
|
||||
233
submodules/SSignalKit/SwiftSignalKit/Disposable.swift
Normal file
233
submodules/SSignalKit/SwiftSignalKit/Disposable.swift
Normal file
@@ -0,0 +1,233 @@
|
||||
import Foundation
|
||||
|
||||
public protocol Disposable: class {
|
||||
func dispose()
|
||||
}
|
||||
|
||||
final class _EmptyDisposable: Disposable {
|
||||
func dispose() {
|
||||
}
|
||||
}
|
||||
|
||||
public let EmptyDisposable: Disposable = _EmptyDisposable()
|
||||
|
||||
public final class ActionDisposable : Disposable {
|
||||
private var lock = pthread_mutex_t()
|
||||
|
||||
private var action: (() -> Void)?
|
||||
|
||||
public init(action: @escaping() -> Void) {
|
||||
self.action = action
|
||||
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
var freeAction: (() -> Void)?
|
||||
pthread_mutex_lock(&self.lock)
|
||||
freeAction = self.action
|
||||
self.action = nil
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if let freeAction = freeAction {
|
||||
withExtendedLifetime(freeAction, {})
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let disposeAction: (() -> Void)?
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
disposeAction = self.action
|
||||
self.action = nil
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
disposeAction?()
|
||||
}
|
||||
}
|
||||
|
||||
public final class MetaDisposable : Disposable {
|
||||
private var lock = pthread_mutex_t()
|
||||
private var disposed = false
|
||||
private var disposable: Disposable! = nil
|
||||
|
||||
public init() {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
var freeDisposable: Disposable?
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if let disposable = self.disposable {
|
||||
freeDisposable = disposable
|
||||
self.disposable = nil
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
if let freeDisposable = freeDisposable {
|
||||
withExtendedLifetime(freeDisposable, { })
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func set(_ disposable: Disposable?) {
|
||||
var previousDisposable: Disposable! = nil
|
||||
var disposeImmediately = false
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
disposeImmediately = self.disposed
|
||||
if !disposeImmediately {
|
||||
previousDisposable = self.disposable
|
||||
if let disposable = disposable {
|
||||
self.disposable = disposable
|
||||
} else {
|
||||
self.disposable = nil
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if previousDisposable != nil {
|
||||
previousDisposable.dispose()
|
||||
}
|
||||
|
||||
if disposeImmediately {
|
||||
if let disposable = disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func dispose()
|
||||
{
|
||||
var disposable: Disposable! = nil
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.disposed {
|
||||
self.disposed = true
|
||||
disposable = self.disposable
|
||||
self.disposable = nil
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if disposable != nil {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class DisposableSet : Disposable {
|
||||
private var lock = pthread_mutex_t()
|
||||
private var disposed = false
|
||||
private var disposables: [Disposable] = []
|
||||
|
||||
public init() {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.disposables.removeAll()
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func add(_ disposable: Disposable) {
|
||||
var disposeImmediately = false
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if self.disposed {
|
||||
disposeImmediately = true
|
||||
} else {
|
||||
self.disposables.append(disposable)
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if disposeImmediately {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func remove(_ disposable: Disposable) {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if let index = self.disposables.index(where: { $0 === disposable }) {
|
||||
self.disposables.remove(at: index)
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
var disposables: [Disposable] = []
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.disposed {
|
||||
self.disposed = true
|
||||
disposables = self.disposables
|
||||
self.disposables = []
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if disposables.count != 0 {
|
||||
for disposable in disposables {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class DisposableDict<T: Hashable> : Disposable {
|
||||
private var lock = pthread_mutex_t()
|
||||
private var disposed = false
|
||||
private var disposables: [T: Disposable] = [:]
|
||||
|
||||
public init() {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.disposables.removeAll()
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func set(_ disposable: Disposable?, forKey key: T) {
|
||||
var disposeImmediately = false
|
||||
var disposePrevious: Disposable?
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if self.disposed {
|
||||
disposeImmediately = true
|
||||
} else {
|
||||
disposePrevious = self.disposables[key]
|
||||
if let disposable = disposable {
|
||||
self.disposables[key] = disposable
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if disposeImmediately {
|
||||
disposable?.dispose()
|
||||
}
|
||||
disposePrevious?.dispose()
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
var disposables: [T: Disposable] = [:]
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.disposed {
|
||||
self.disposed = true
|
||||
disposables = self.disposables
|
||||
self.disposables = [:]
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if disposables.count != 0 {
|
||||
for disposable in disposables.values {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
submodules/SSignalKit/SwiftSignalKit/Info.plist
Normal file
26
submodules/SSignalKit/SwiftSignalKit/Info.plist
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
19
submodules/SSignalKit/SwiftSignalKit/Lock.swift
Normal file
19
submodules/SSignalKit/SwiftSignalKit/Lock.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
import Foundation
|
||||
|
||||
public final class Lock {
|
||||
private var mutex = pthread_mutex_t()
|
||||
|
||||
public init() {
|
||||
pthread_mutex_init(&self.mutex, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.mutex)
|
||||
}
|
||||
|
||||
public func locked(_ f: () -> ()) {
|
||||
pthread_mutex_lock(&self.mutex)
|
||||
f()
|
||||
pthread_mutex_unlock(&self.mutex)
|
||||
}
|
||||
}
|
||||
88
submodules/SSignalKit/SwiftSignalKit/Multicast.swift
Normal file
88
submodules/SSignalKit/SwiftSignalKit/Multicast.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
import Foundation
|
||||
|
||||
private final class MulticastInstance<T> {
|
||||
let disposable: Disposable
|
||||
var subscribers = Bag<(T) -> Void>()
|
||||
var lock = Lock()
|
||||
|
||||
init(disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
}
|
||||
|
||||
public final class Multicast<T> {
|
||||
private let lock = Lock()
|
||||
private var instances: [String: MulticastInstance<T>] = [:]
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func get(key: String, signal: Signal<T, NoError>) -> Signal<T, NoError> {
|
||||
return Signal { subscriber in
|
||||
var instance: MulticastInstance<T>!
|
||||
var beginDisposable: MetaDisposable?
|
||||
self.lock.locked {
|
||||
if let existing = self.instances[key] {
|
||||
instance = existing
|
||||
} else {
|
||||
let disposable = MetaDisposable()
|
||||
instance = MulticastInstance(disposable: disposable)
|
||||
beginDisposable = disposable
|
||||
}
|
||||
}
|
||||
|
||||
var index: Bag<(T) -> Void>.Index!
|
||||
instance.lock.locked {
|
||||
index = instance.subscribers.add({ next in
|
||||
subscriber.putNext(next)
|
||||
})
|
||||
}
|
||||
|
||||
if let beginDisposable = beginDisposable {
|
||||
beginDisposable.set(signal.start(next: { next in
|
||||
var subscribers: [(T) -> Void]!
|
||||
instance.lock.locked {
|
||||
subscribers = instance.subscribers.copyItems()
|
||||
}
|
||||
for subscriber in subscribers {
|
||||
subscriber(next)
|
||||
}
|
||||
}, error: { _ in
|
||||
self.lock.locked {
|
||||
let _ = self.instances.removeValue(forKey: key)
|
||||
}
|
||||
}, completed: {
|
||||
self.lock.locked {
|
||||
self.instances.removeValue(forKey: key)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
return ActionDisposable {
|
||||
var remove = false
|
||||
instance.lock.locked {
|
||||
instance.subscribers.remove(index)
|
||||
if instance.subscribers.isEmpty {
|
||||
remove = true
|
||||
}
|
||||
}
|
||||
|
||||
if remove {
|
||||
self.lock.locked {
|
||||
let _ = self.instances.removeValue(forKey: key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class MulticastPromise<T> {
|
||||
public let subscribers = Bag<(T) -> Void>()
|
||||
public let lock = Lock()
|
||||
public var value: T?
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
}
|
||||
139
submodules/SSignalKit/SwiftSignalKit/Promise.swift
Normal file
139
submodules/SSignalKit/SwiftSignalKit/Promise.swift
Normal file
@@ -0,0 +1,139 @@
|
||||
import Foundation
|
||||
|
||||
public final class Promise<T> {
|
||||
private var initializeOnFirstAccess: Signal<T, NoError>?
|
||||
private var value: T?
|
||||
private var lock = pthread_mutex_t()
|
||||
private let disposable = MetaDisposable()
|
||||
private let subscribers = Bag<(T) -> Void>()
|
||||
|
||||
public var onDeinit: (() -> Void)?
|
||||
|
||||
public init(initializeOnFirstAccess: Signal<T, NoError>?) {
|
||||
self.initializeOnFirstAccess = initializeOnFirstAccess
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
public init(_ value: T) {
|
||||
self.value = value
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
public init() {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.onDeinit?()
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
public func set(_ signal: Signal<T, NoError>) {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.value = nil
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
self.disposable.set(signal.start(next: { [weak self] next in
|
||||
if let strongSelf = self {
|
||||
pthread_mutex_lock(&strongSelf.lock)
|
||||
strongSelf.value = next
|
||||
let subscribers = strongSelf.subscribers.copyItems()
|
||||
pthread_mutex_unlock(&strongSelf.lock)
|
||||
|
||||
for subscriber in subscribers {
|
||||
subscriber(next)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
public func get() -> Signal<T, NoError> {
|
||||
return Signal { subscriber in
|
||||
pthread_mutex_lock(&self.lock)
|
||||
var initializeOnFirstAccessNow: Signal<T, NoError>?
|
||||
if let initializeOnFirstAccess = self.initializeOnFirstAccess {
|
||||
initializeOnFirstAccessNow = initializeOnFirstAccess
|
||||
self.initializeOnFirstAccess = nil
|
||||
}
|
||||
let currentValue = self.value
|
||||
let index = self.subscribers.add({ next in
|
||||
subscriber.putNext(next)
|
||||
})
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if let currentValue = currentValue {
|
||||
subscriber.putNext(currentValue)
|
||||
}
|
||||
|
||||
if let initializeOnFirstAccessNow = initializeOnFirstAccessNow {
|
||||
self.set(initializeOnFirstAccessNow)
|
||||
}
|
||||
|
||||
return ActionDisposable {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.subscribers.remove(index)
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ValuePromise<T: Equatable> {
|
||||
private var value: T?
|
||||
private var lock = pthread_mutex_t()
|
||||
private let subscribers = Bag<(T) -> Void>()
|
||||
public let ignoreRepeated: Bool
|
||||
|
||||
public init(_ value: T, ignoreRepeated: Bool = false) {
|
||||
self.value = value
|
||||
self.ignoreRepeated = ignoreRepeated
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
public init(ignoreRepeated: Bool = false) {
|
||||
self.ignoreRepeated = ignoreRepeated
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
public func set(_ value: T) {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
let subscribers: [(T) -> Void]
|
||||
if !self.ignoreRepeated || self.value != value {
|
||||
self.value = value
|
||||
subscribers = self.subscribers.copyItems()
|
||||
} else {
|
||||
subscribers = []
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock);
|
||||
|
||||
for subscriber in subscribers {
|
||||
subscriber(value)
|
||||
}
|
||||
}
|
||||
|
||||
public func get() -> Signal<T, NoError> {
|
||||
return Signal { subscriber in
|
||||
pthread_mutex_lock(&self.lock)
|
||||
let currentValue = self.value
|
||||
let index = self.subscribers.add({ next in
|
||||
subscriber.putNext(next)
|
||||
})
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if let currentValue = currentValue {
|
||||
subscriber.putNext(currentValue)
|
||||
}
|
||||
|
||||
return ActionDisposable {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.subscribers.remove(index)
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
submodules/SSignalKit/SwiftSignalKit/Queue.swift
Normal file
88
submodules/SSignalKit/SwiftSignalKit/Queue.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
import Foundation
|
||||
|
||||
private let QueueSpecificKey = DispatchSpecificKey<NSObject>()
|
||||
|
||||
private let globalMainQueue = Queue(queue: DispatchQueue.main, specialIsMainQueue: true)
|
||||
private let globalDefaultQueue = Queue(queue: DispatchQueue.global(qos: .default), specialIsMainQueue: false)
|
||||
private let globalBackgroundQueue = Queue(queue: DispatchQueue.global(qos: .background), specialIsMainQueue: false)
|
||||
|
||||
public final class Queue {
|
||||
private let nativeQueue: DispatchQueue
|
||||
private var specific = NSObject()
|
||||
private let specialIsMainQueue: Bool
|
||||
|
||||
public var queue: DispatchQueue {
|
||||
get {
|
||||
return self.nativeQueue
|
||||
}
|
||||
}
|
||||
|
||||
public class func mainQueue() -> Queue {
|
||||
return globalMainQueue
|
||||
}
|
||||
|
||||
public class func concurrentDefaultQueue() -> Queue {
|
||||
return globalDefaultQueue
|
||||
}
|
||||
|
||||
public class func concurrentBackgroundQueue() -> Queue {
|
||||
return globalBackgroundQueue
|
||||
}
|
||||
|
||||
public init(queue: DispatchQueue) {
|
||||
self.nativeQueue = queue
|
||||
self.specialIsMainQueue = false
|
||||
}
|
||||
|
||||
fileprivate init(queue: DispatchQueue, specialIsMainQueue: Bool) {
|
||||
self.nativeQueue = queue
|
||||
self.specialIsMainQueue = specialIsMainQueue
|
||||
}
|
||||
|
||||
public init(name: String? = nil, qos: DispatchQoS = .default) {
|
||||
self.nativeQueue = DispatchQueue(label: name ?? "", qos: qos)
|
||||
|
||||
self.specialIsMainQueue = false
|
||||
|
||||
self.nativeQueue.setSpecific(key: QueueSpecificKey, value: self.specific)
|
||||
}
|
||||
|
||||
public func isCurrent() -> Bool {
|
||||
if DispatchQueue.getSpecific(key: QueueSpecificKey) === self.specific {
|
||||
return true
|
||||
} else if self.specialIsMainQueue && Thread.isMainThread {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func async(_ f: @escaping () -> Void) {
|
||||
if self.isCurrent() {
|
||||
f()
|
||||
} else {
|
||||
self.nativeQueue.async(execute: f)
|
||||
}
|
||||
}
|
||||
|
||||
public func sync(_ f: () -> Void) {
|
||||
if self.isCurrent() {
|
||||
f()
|
||||
} else {
|
||||
self.nativeQueue.sync(execute: f)
|
||||
}
|
||||
}
|
||||
|
||||
public func justDispatch(_ f: @escaping () -> Void) {
|
||||
self.nativeQueue.async(execute: f)
|
||||
}
|
||||
|
||||
public func justDispatchWithQoS(qos: DispatchQoS, _ f: @escaping () -> Void) {
|
||||
self.nativeQueue.async(group: nil, qos: qos, flags: [.enforceQoS], execute: f)
|
||||
}
|
||||
|
||||
public func after(_ delay: Double, _ f: @escaping() -> Void) {
|
||||
let time: DispatchTime = DispatchTime.now() + delay
|
||||
self.nativeQueue.asyncAfter(deadline: time, execute: f)
|
||||
}
|
||||
}
|
||||
53
submodules/SSignalKit/SwiftSignalKit/QueueLocalObject.swift
Normal file
53
submodules/SSignalKit/SwiftSignalKit/QueueLocalObject.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
import Foundation
|
||||
|
||||
public final class QueueLocalObject<T: AnyObject> {
|
||||
private let queue: Queue
|
||||
private var valueRef: Unmanaged<T>?
|
||||
|
||||
public init(queue: Queue, generate: @escaping () -> T) {
|
||||
self.queue = queue
|
||||
|
||||
self.queue.async {
|
||||
let value = generate()
|
||||
self.valueRef = Unmanaged.passRetained(value)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
let valueRef = self.valueRef
|
||||
self.queue.async {
|
||||
valueRef?.release()
|
||||
}
|
||||
}
|
||||
|
||||
public func with(_ f: @escaping (T) -> Void) {
|
||||
self.queue.async {
|
||||
if let valueRef = self.valueRef {
|
||||
let value = valueRef.takeUnretainedValue()
|
||||
f(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func syncWith<R>(_ f: @escaping (T) -> R) -> R? {
|
||||
var result: R?
|
||||
self.queue.sync {
|
||||
if let valueRef = self.valueRef {
|
||||
let value = valueRef.takeUnretainedValue()
|
||||
result = f(value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public func signalWith<R, E>(_ f: @escaping (T, Subscriber<R, E>) -> Disposable) -> Signal<R, E> {
|
||||
return Signal { [weak self] subscriber in
|
||||
if let strongSelf = self, let valueRef = strongSelf.valueRef {
|
||||
let value = valueRef.takeUnretainedValue()
|
||||
return f(value, subscriber)
|
||||
} else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
} |> runOn(self.queue)
|
||||
}
|
||||
}
|
||||
85
submodules/SSignalKit/SwiftSignalKit/Signal.swift
Normal file
85
submodules/SSignalKit/SwiftSignalKit/Signal.swift
Normal file
@@ -0,0 +1,85 @@
|
||||
import Foundation
|
||||
|
||||
let doNothing: () -> Void = { }
|
||||
|
||||
public enum NoValue {
|
||||
}
|
||||
|
||||
public enum NoError {
|
||||
}
|
||||
|
||||
public func identity<A>(a: A) -> A {
|
||||
return a
|
||||
}
|
||||
|
||||
precedencegroup PipeRight {
|
||||
associativity: left
|
||||
higherThan: DefaultPrecedence
|
||||
}
|
||||
|
||||
infix operator |> : PipeRight
|
||||
|
||||
public func |> <T, U>(value: T, function: ((T) -> U)) -> U {
|
||||
return function(value)
|
||||
}
|
||||
|
||||
private final class SubscriberDisposable<T, E> : Disposable {
|
||||
private let subscriber: Subscriber<T, E>
|
||||
private let disposable: Disposable
|
||||
|
||||
init(subscriber: Subscriber<T, E>, disposable: Disposable) {
|
||||
self.subscriber = subscriber
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
subscriber.markTerminatedWithoutDisposal()
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public struct Signal<T, E> {
|
||||
private let generator: (Subscriber<T, E>) -> Disposable
|
||||
|
||||
public init(_ generator: @escaping(Subscriber<T, E>) -> Disposable) {
|
||||
self.generator = generator
|
||||
}
|
||||
|
||||
public func start(next: ((T) -> Void)! = nil, error: ((E) -> Void)! = nil, completed: (() -> Void)! = nil) -> Disposable {
|
||||
let subscriber = Subscriber<T, E>(next: next, error: error, completed: completed)
|
||||
let disposable = self.generator(subscriber)
|
||||
subscriber.assignDisposable(disposable)
|
||||
return SubscriberDisposable(subscriber: subscriber, disposable: disposable)
|
||||
}
|
||||
|
||||
public static func single(_ value: T) -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putNext(value)
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public static func complete() -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public static func fail(_ error: E) -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putError(error)
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public static func never() -> Signal<T, E> {
|
||||
return Signal<T, E> { _ in
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
168
submodules/SSignalKit/SwiftSignalKit/Signal_Catch.swift
Normal file
168
submodules/SSignalKit/SwiftSignalKit/Signal_Catch.swift
Normal file
@@ -0,0 +1,168 @@
|
||||
import Foundation
|
||||
|
||||
public func `catch`<T, E, R>(_ f: @escaping(E) -> Signal<T, R>) -> (Signal<T, E>) -> Signal<T, R> {
|
||||
return { signal in
|
||||
return Signal<T, R> { subscriber in
|
||||
let disposable = DisposableSet()
|
||||
|
||||
disposable.add(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
let anotherSignal = f(error)
|
||||
|
||||
disposable.add(anotherSignal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func recursiveFunction(_ f: @escaping(@escaping() -> Void) -> Void) -> (() -> Void) {
|
||||
return {
|
||||
f(recursiveFunction(f))
|
||||
}
|
||||
}
|
||||
|
||||
public func restart<T, E>(_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let shouldRestart = Atomic(value: true)
|
||||
let currentDisposable = MetaDisposable()
|
||||
|
||||
let start = recursiveFunction { recurse in
|
||||
let currentShouldRestart = shouldRestart.with { value in
|
||||
return value
|
||||
}
|
||||
if currentShouldRestart {
|
||||
let disposable = signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
recurse()
|
||||
})
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
return ActionDisposable {
|
||||
currentDisposable.dispose()
|
||||
let _ = shouldRestart.swap(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func recurse<T, E>(_ latestValue: T?) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let shouldRestart = Atomic(value: true)
|
||||
let currentDisposable = MetaDisposable()
|
||||
|
||||
let start = recursiveFunction { recurse in
|
||||
let currentShouldRestart = shouldRestart.with { value in
|
||||
return value
|
||||
}
|
||||
if currentShouldRestart {
|
||||
let disposable = signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
recurse()
|
||||
})
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
return ActionDisposable {
|
||||
currentDisposable.dispose()
|
||||
let _ = shouldRestart.swap(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func retry<T, E>(_ delayIncrement: Double, maxDelay: Double, onQueue queue: Queue) -> (_ signal: Signal<T, E>) -> Signal<T, NoError> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let shouldRetry = Atomic(value: true)
|
||||
let currentDelay = Atomic(value: 0.0)
|
||||
let currentDisposable = MetaDisposable()
|
||||
|
||||
let start = recursiveFunction { recurse in
|
||||
let currentShouldRetry = shouldRetry.with { value in
|
||||
return value
|
||||
}
|
||||
if currentShouldRetry {
|
||||
let disposable = signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
let delay = currentDelay.modify { value in
|
||||
return min(maxDelay, value + delayIncrement)
|
||||
}
|
||||
|
||||
let time: DispatchTime = DispatchTime.now() + Double(delay)
|
||||
queue.queue.asyncAfter(deadline: time, execute: {
|
||||
recurse()
|
||||
})
|
||||
}, completed: {
|
||||
let _ = shouldRetry.swap(false)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
return ActionDisposable {
|
||||
currentDisposable.dispose()
|
||||
let _ = shouldRetry.swap(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func restartIfError<T, E>(_ signal: Signal<T, E>) -> Signal<T, NoError> {
|
||||
return Signal<T, NoError> { subscriber in
|
||||
let shouldRetry = Atomic(value: true)
|
||||
let currentDisposable = MetaDisposable()
|
||||
|
||||
let start = recursiveFunction { recurse in
|
||||
let currentShouldRetry = shouldRetry.with { value in
|
||||
return value
|
||||
}
|
||||
if currentShouldRetry {
|
||||
let disposable = signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
recurse()
|
||||
}, completed: {
|
||||
let _ = shouldRetry.swap(false)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
return ActionDisposable {
|
||||
currentDisposable.dispose()
|
||||
let _ = shouldRetry.swap(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
163
submodules/SSignalKit/SwiftSignalKit/Signal_Combine.swift
Normal file
163
submodules/SSignalKit/SwiftSignalKit/Signal_Combine.swift
Normal file
@@ -0,0 +1,163 @@
|
||||
import Foundation
|
||||
|
||||
private struct SignalCombineState {
|
||||
let values: [Int : Any]
|
||||
let completed: Set<Int>
|
||||
let error: Bool
|
||||
}
|
||||
|
||||
private func combineLatestAny<E, R>(_ signals: [Signal<Any, E>], combine: @escaping([Any]) -> R, initialValues: [Int : Any], queue: Queue?) -> Signal<R, E> {
|
||||
return Signal { subscriber in
|
||||
let state = Atomic(value: SignalCombineState(values: initialValues, completed: Set(), error: false))
|
||||
let disposable = DisposableSet()
|
||||
|
||||
if initialValues.count == signals.count {
|
||||
var values: [Any] = []
|
||||
for i in 0 ..< initialValues.count {
|
||||
values.append(initialValues[i]!)
|
||||
}
|
||||
subscriber.putNext(combine(values))
|
||||
}
|
||||
|
||||
let count = signals.count
|
||||
for iterationIndex in 0 ..< count {
|
||||
let index = iterationIndex
|
||||
var signal = signals[index]
|
||||
if let queue = queue {
|
||||
signal = signal
|
||||
|> deliverOn(queue)
|
||||
}
|
||||
let signalDisposable = signal.start(next: { next in
|
||||
let currentState = state.modify { current in
|
||||
var values = current.values
|
||||
values[index] = next
|
||||
return SignalCombineState(values: values, completed: current.completed, error: current.error)
|
||||
}
|
||||
if currentState.values.count == count {
|
||||
var values: [Any] = []
|
||||
for i in 0 ..< count {
|
||||
values.append(currentState.values[i]!)
|
||||
}
|
||||
subscriber.putNext(combine(values))
|
||||
}
|
||||
}, error: { error in
|
||||
var emitError = false
|
||||
let _ = state.modify { current in
|
||||
if !current.error {
|
||||
emitError = true
|
||||
return SignalCombineState(values: current.values, completed: current.completed, error: true)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
}
|
||||
if emitError {
|
||||
subscriber.putError(error)
|
||||
}
|
||||
}, completed: {
|
||||
var emitCompleted = false
|
||||
let _ = state.modify { current in
|
||||
if !current.completed.contains(index) {
|
||||
var completed = current.completed
|
||||
completed.insert(index)
|
||||
emitCompleted = completed.count == count
|
||||
return SignalCombineState(values: current.values, completed: completed, error: current.error)
|
||||
}
|
||||
return current
|
||||
}
|
||||
if emitCompleted {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
|
||||
disposable.add(signalDisposable)
|
||||
}
|
||||
|
||||
return disposable;
|
||||
}
|
||||
}
|
||||
|
||||
private func signalOfAny<T, E>(_ signal: Signal<T, E>) -> Signal<Any, E> {
|
||||
return Signal { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>) -> Signal<(T1, T2), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ v1: T1, _ s2: Signal<T2, E>, _ v2: T2) -> Signal<(T1, T2), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2)
|
||||
}, initialValues: [0: v1, 1: v2], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>) -> Signal<(T1, T2, T3), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>) -> Signal<(T1, T2, T3, T4), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>) -> Signal<(T1, T2, T3, T4, T5), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>) -> Signal<(T1, T2, T3, T4, T5, T6), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>, _ s8: Signal<T8, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7, T8), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7), signalOfAny(s8)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7, values[7] as! T8)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>, _ s8: Signal<T8, E>, _ s9: Signal<T9, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7, T8, T9), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7), signalOfAny(s8), signalOfAny(s9)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7, values[7] as! T8, values[8] as! T9)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>, _ s8: Signal<T8, E>, _ s9: Signal<T9, E>, _ s10: Signal<T10, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7), signalOfAny(s8), signalOfAny(s9), signalOfAny(s10)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7, values[7] as! T8, values[8] as! T9, values[9] as! T10)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T, E>(queue: Queue? = nil, _ signals: [Signal<T, E>]) -> Signal<[T], E> {
|
||||
if signals.count == 0 {
|
||||
return single([T](), E.self)
|
||||
}
|
||||
|
||||
return combineLatestAny(signals.map({signalOfAny($0)}), combine: { values in
|
||||
var combined: [T] = []
|
||||
for value in values {
|
||||
combined.append(value as! T)
|
||||
}
|
||||
return combined
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
122
submodules/SSignalKit/SwiftSignalKit/Signal_Dispatch.swift
Normal file
122
submodules/SSignalKit/SwiftSignalKit/Signal_Dispatch.swift
Normal file
@@ -0,0 +1,122 @@
|
||||
import Foundation
|
||||
|
||||
public func deliverOn<T, E>(_ queue: Queue) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
return signal.start(next: { next in
|
||||
queue.async {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
}, error: { error in
|
||||
queue.async {
|
||||
subscriber.putError(error)
|
||||
}
|
||||
}, completed: {
|
||||
queue.async {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func deliverOnMainQueue<T, E>(_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return signal |> deliverOn(Queue.mainQueue())
|
||||
}
|
||||
|
||||
public func deliverOn<T, E>(_ threadPool: ThreadPool) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let queue = threadPool.nextQueue()
|
||||
return signal.start(next: { next in
|
||||
queue.addTask(ThreadPoolTask { state in
|
||||
if !state.cancelled.with { $0 } {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
})
|
||||
}, error: { error in
|
||||
queue.addTask(ThreadPoolTask { state in
|
||||
if !state.cancelled.with { $0 } {
|
||||
subscriber.putError(error)
|
||||
}
|
||||
})
|
||||
}, completed: {
|
||||
queue.addTask(ThreadPoolTask { state in
|
||||
if !state.cancelled.with { $0 } {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func runOn<T, E>(_ queue: Queue) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
if queue.isCurrent() {
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
} else {
|
||||
var cancelled = false
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
cancelled = true
|
||||
})
|
||||
|
||||
queue.async {
|
||||
if cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
disposable.set(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func runOn<T, E>(_ threadPool: ThreadPool) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let cancelled = false
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
let task = ThreadPoolTask { state in
|
||||
if cancelled || state.cancelled.with { $0 } {
|
||||
return
|
||||
}
|
||||
|
||||
disposable.set(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
task.cancel()
|
||||
})
|
||||
|
||||
threadPool.addTask(task)
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
46
submodules/SSignalKit/SwiftSignalKit/Signal_Loop.swift
Normal file
46
submodules/SSignalKit/SwiftSignalKit/Signal_Loop.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
import Foundation
|
||||
|
||||
public enum SignalFeedbackLoopState<T> {
|
||||
case initial
|
||||
case loop(T)
|
||||
}
|
||||
|
||||
public func feedbackLoop<R1, R, E>(once: @escaping (SignalFeedbackLoopState<R1>) -> Signal<R1, E>?, reduce: @escaping (R1, R1) -> R1) -> Signal<R, E> {
|
||||
return Signal { subscriber in
|
||||
let currentDisposable = MetaDisposable()
|
||||
|
||||
let state = Atomic<R1?>(value: nil)
|
||||
|
||||
var loopAgain: (() -> Void)?
|
||||
|
||||
let loopOnce: (MetaDisposable?) -> Void = { disposable in
|
||||
if let signal = once(.initial) {
|
||||
disposable?.set(signal.start(next: { next in
|
||||
let _ = state.modify { value in
|
||||
if let value = value {
|
||||
return reduce(value, next)
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
loopAgain?()
|
||||
}))
|
||||
} else {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
loopAgain = { [weak currentDisposable] in
|
||||
loopOnce(currentDisposable)
|
||||
}
|
||||
|
||||
loopOnce(currentDisposable)
|
||||
|
||||
return ActionDisposable {
|
||||
currentDisposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
128
submodules/SSignalKit/SwiftSignalKit/Signal_Mapping.swift
Normal file
128
submodules/SSignalKit/SwiftSignalKit/Signal_Mapping.swift
Normal file
@@ -0,0 +1,128 @@
|
||||
import Foundation
|
||||
|
||||
public func map<T, E, R>(_ f: @escaping(T) -> R) -> (Signal<T, E>) -> Signal<R, E> {
|
||||
return { signal in
|
||||
return Signal<R, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(f(next))
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func filter<T, E>(_ f: @escaping(T) -> Bool) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
if f(next) {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func flatMap<T, E, R>(_ f: @escaping (T) -> R?) -> (Signal<T, E>) -> Signal<R, E> {
|
||||
return { signal in
|
||||
return Signal<R, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
if let value = f(next) {
|
||||
subscriber.putNext(value)
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func mapError<T, E, R>(_ f: @escaping(E) -> R) -> (Signal<T, E>) -> Signal<T, R> {
|
||||
return { signal in
|
||||
return Signal<T, R> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(f(error))
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func introduceError<T, E>(_ type: E.Type) -> (Signal<T, NoError>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { _ in
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DistinctUntilChangedContext<T> {
|
||||
var value: T?
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<T: Equatable, E>(_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let context = Atomic(value: DistinctUntilChangedContext<T>())
|
||||
|
||||
return signal.start(next: { next in
|
||||
let pass = context.with { context -> Bool in
|
||||
if let value = context.value, value == next {
|
||||
return false
|
||||
} else {
|
||||
context.value = next
|
||||
return true
|
||||
}
|
||||
}
|
||||
if pass {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<T, E>(isEqual: @escaping (T, T) -> Bool) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let context = Atomic(value: DistinctUntilChangedContext<T>())
|
||||
|
||||
return signal.start(next: { next in
|
||||
let pass = context.with { context -> Bool in
|
||||
if let value = context.value, isEqual(value, next) {
|
||||
return false
|
||||
} else {
|
||||
context.value = next
|
||||
return true
|
||||
}
|
||||
}
|
||||
if pass {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Foundation
|
||||
|
||||
public enum SignalEvent<T, E> {
|
||||
case Next(T)
|
||||
case Error(E)
|
||||
case Completion
|
||||
}
|
||||
|
||||
public func dematerialize<T, E>(signal: Signal<T, E>) -> Signal<SignalEvent<T, E>, NoError> {
|
||||
return Signal { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(.Next(next))
|
||||
}, error: { error in
|
||||
subscriber.putNext(.Error(error))
|
||||
subscriber.putCompletion()
|
||||
}, completed: {
|
||||
subscriber.putNext(.Completion)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func materialize<T, E>(signal: Signal<SignalEvent<T, E>, NoError>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
return signal.start(next: { next in
|
||||
switch next {
|
||||
case let .Next(next):
|
||||
subscriber.putNext(next)
|
||||
case let .Error(error):
|
||||
subscriber.putError(error)
|
||||
case .Completion:
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}, error: { _ in
|
||||
subscriber.putCompletion()
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
7
submodules/SSignalKit/SwiftSignalKit/Signal_Merge.swift
Normal file
7
submodules/SSignalKit/SwiftSignalKit/Signal_Merge.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
/*public func merge<T, E>(signal1: Signal<T, E>, signal2: Signal<T, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
|
||||
}
|
||||
}*/
|
||||
248
submodules/SSignalKit/SwiftSignalKit/Signal_Meta.swift
Normal file
248
submodules/SSignalKit/SwiftSignalKit/Signal_Meta.swift
Normal file
@@ -0,0 +1,248 @@
|
||||
import Foundation
|
||||
|
||||
private final class SignalQueueState<T, E>: Disposable {
|
||||
var lock = pthread_mutex_t()
|
||||
var executingSignal = false
|
||||
var terminated = false
|
||||
|
||||
var disposable: Disposable = EmptyDisposable
|
||||
let currentDisposable = MetaDisposable()
|
||||
var subscriber: Subscriber<T, E>?
|
||||
|
||||
var queuedSignals: [Signal<T, E>] = []
|
||||
let queueMode: Bool
|
||||
let throttleMode: Bool
|
||||
|
||||
init(subscriber: Subscriber<T, E>, queueMode: Bool, throttleMode: Bool) {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
|
||||
self.subscriber = subscriber
|
||||
self.queueMode = queueMode
|
||||
self.throttleMode = throttleMode
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
func beginWithDisposable(_ disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func enqueueSignal(_ signal: Signal<T, E>) {
|
||||
var startSignal = false
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if self.queueMode && self.executingSignal {
|
||||
if self.throttleMode {
|
||||
self.queuedSignals.removeAll()
|
||||
}
|
||||
self.queuedSignals.append(signal)
|
||||
} else {
|
||||
self.executingSignal = true
|
||||
startSignal = true
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if startSignal {
|
||||
let disposable = signal.start(next: { next in
|
||||
assert(self.subscriber != nil)
|
||||
self.subscriber?.putNext(next)
|
||||
}, error: { error in
|
||||
assert(self.subscriber != nil)
|
||||
self.subscriber?.putError(error)
|
||||
}, completed: {
|
||||
self.headCompleted()
|
||||
})
|
||||
self.currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
func headCompleted() {
|
||||
while true {
|
||||
let leftFunction = Atomic(value: false)
|
||||
|
||||
var nextSignal: Signal<T, E>! = nil
|
||||
|
||||
var terminated = false
|
||||
pthread_mutex_lock(&self.lock)
|
||||
self.executingSignal = false
|
||||
if self.queueMode {
|
||||
if self.queuedSignals.count != 0 {
|
||||
nextSignal = self.queuedSignals[0]
|
||||
self.queuedSignals.remove(at: 0)
|
||||
self.executingSignal = true
|
||||
} else {
|
||||
terminated = self.terminated
|
||||
}
|
||||
} else {
|
||||
terminated = self.terminated
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if terminated {
|
||||
self.subscriber?.putCompletion()
|
||||
} else if nextSignal != nil {
|
||||
let disposable = nextSignal.start(next: { next in
|
||||
assert(self.subscriber != nil)
|
||||
self.subscriber?.putNext(next)
|
||||
}, error: { error in
|
||||
assert(self.subscriber != nil)
|
||||
self.subscriber?.putError(error)
|
||||
}, completed: {
|
||||
if leftFunction.swap(true) == true {
|
||||
self.headCompleted()
|
||||
}
|
||||
})
|
||||
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
|
||||
if leftFunction.swap(true) == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func beginCompletion() {
|
||||
var executingSignal = false
|
||||
pthread_mutex_lock(&self.lock)
|
||||
executingSignal = self.executingSignal
|
||||
self.terminated = true
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if !executingSignal {
|
||||
self.subscriber?.putCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.currentDisposable.dispose()
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func switchToLatest<T, E>(_ signal: Signal<Signal<T, E>, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let state = SignalQueueState(subscriber: subscriber, queueMode: false, throttleMode: false)
|
||||
state.beginWithDisposable(signal.start(next: { next in
|
||||
state.enqueueSignal(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
state.beginCompletion()
|
||||
}))
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
public func queue<T, E>(_ signal: Signal<Signal<T, E>, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let state = SignalQueueState(subscriber: subscriber, queueMode: true, throttleMode: false)
|
||||
state.beginWithDisposable(signal.start(next: { next in
|
||||
state.enqueueSignal(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
state.beginCompletion()
|
||||
}))
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
public func throttled<T, E>(_ signal: Signal<Signal<T, E>, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let state = SignalQueueState(subscriber: subscriber, queueMode: true, throttleMode: true)
|
||||
state.beginWithDisposable(signal.start(next: { next in
|
||||
state.enqueueSignal(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
state.beginCompletion()
|
||||
}))
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
public func mapToSignal<T, R, E>(_ f: @escaping(T) -> Signal<R, E>) -> (Signal<T, E>) -> Signal<R, E> {
|
||||
return { signal -> Signal<R, E> in
|
||||
return Signal<Signal<R, E>, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(f(next))
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
} |> switchToLatest
|
||||
}
|
||||
}
|
||||
|
||||
public func ignoreValues<T, E>(_ signal: Signal<T, E>) -> Signal<Never, E> {
|
||||
return Signal { subscriber in
|
||||
return signal.start(error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func mapToSignalPromotingError<T, R, E>(_ f: @escaping(T) -> Signal<R, E>) -> (Signal<T, NoError>) -> Signal<R, E> {
|
||||
return { signal -> Signal<R, E> in
|
||||
return Signal<Signal<R, E>, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(f(next))
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
} |> switchToLatest
|
||||
}
|
||||
}
|
||||
|
||||
public func mapToQueue<T, R, E>(_ f: @escaping(T) -> Signal<R, E>) -> (Signal<T, E>) -> Signal<R, E> {
|
||||
return { signal -> Signal<R, E> in
|
||||
return signal |> map { f($0) } |> queue
|
||||
}
|
||||
}
|
||||
|
||||
public func mapToThrottled<T, R, E>(_ f: @escaping(T) -> Signal<R, E>) -> (Signal<T, E>) -> Signal<R, E> {
|
||||
return { signal -> Signal<R, E> in
|
||||
return signal |> map { f($0) } |> throttled
|
||||
}
|
||||
}
|
||||
|
||||
public func then<T, E>(_ nextSignal: Signal<T, E>) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal -> Signal<T, E> in
|
||||
return Signal<T, E> { subscriber in
|
||||
let disposable = DisposableSet()
|
||||
|
||||
disposable.add(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
disposable.add(nextSignal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}))
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func deferred<T, E>(_ generator: @escaping() -> Signal<T, E>) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
return generator().start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
189
submodules/SSignalKit/SwiftSignalKit/Signal_Reduce.swift
Normal file
189
submodules/SSignalKit/SwiftSignalKit/Signal_Reduce.swift
Normal file
@@ -0,0 +1,189 @@
|
||||
import Foundation
|
||||
|
||||
public func reduceLeft<T, E>(value: T, f: @escaping(T, T) -> T) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
var currentValue = value
|
||||
|
||||
return signal.start(next: { next in
|
||||
currentValue = f(currentValue, next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putNext(currentValue)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func reduceLeft<T, E>(value: T, f: @escaping(T, T, (T) -> Void) -> T) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
var currentValue = value
|
||||
let emit: (T) -> Void = { next in
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
|
||||
return signal.start(next: { next in
|
||||
currentValue = f(currentValue, next, emit)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putNext(currentValue)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Passthrough<T> {
|
||||
case None
|
||||
case Some(T)
|
||||
}
|
||||
|
||||
private final class ReduceQueueState<T, E> : Disposable {
|
||||
var lock: OSSpinLock = 0
|
||||
var executingSignal = false
|
||||
var terminated = false
|
||||
|
||||
var disposable: Disposable = EmptyDisposable
|
||||
let currentDisposable = MetaDisposable()
|
||||
let subscriber: Subscriber<T, E>
|
||||
|
||||
var queuedValues: [T] = []
|
||||
var generator: (T, T) -> Signal<(T, Passthrough<T>), E>
|
||||
var value: T
|
||||
|
||||
init(subscriber: Subscriber<T, E>, value: T, generator: @escaping(T, T) -> Signal<(T, Passthrough<T>), E>) {
|
||||
self.subscriber = subscriber
|
||||
self.generator = generator
|
||||
self.value = value
|
||||
}
|
||||
|
||||
func beginWithDisposable(_ disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func enqueueNext(_ next: T) {
|
||||
var startSignal = false
|
||||
var currentValue: T
|
||||
OSSpinLockLock(&self.lock)
|
||||
currentValue = self.value
|
||||
if self.executingSignal {
|
||||
self.queuedValues.append(next)
|
||||
} else {
|
||||
self.executingSignal = true
|
||||
startSignal = true
|
||||
}
|
||||
OSSpinLockUnlock(&self.lock)
|
||||
|
||||
if startSignal {
|
||||
let disposable = generator(currentValue, next).start(next: { next in
|
||||
self.updateValue(next.0)
|
||||
switch next.1 {
|
||||
case let .Some(value):
|
||||
self.subscriber.putNext(value)
|
||||
case .None:
|
||||
break
|
||||
}
|
||||
}, error: { error in
|
||||
self.subscriber.putError(error)
|
||||
}, completed: {
|
||||
self.headCompleted()
|
||||
})
|
||||
self.currentDisposable.set(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
func updateValue(_ value: T) {
|
||||
OSSpinLockLock(&self.lock)
|
||||
self.value = value
|
||||
OSSpinLockUnlock(&self.lock)
|
||||
}
|
||||
|
||||
func headCompleted() {
|
||||
while true {
|
||||
let leftFunction = Atomic(value: false)
|
||||
|
||||
var nextSignal: Signal<(T, Passthrough<T>), E>! = nil
|
||||
|
||||
var terminated = false
|
||||
var currentValue: T!
|
||||
OSSpinLockLock(&self.lock)
|
||||
self.executingSignal = false
|
||||
if self.queuedValues.count != 0 {
|
||||
nextSignal = self.generator(self.value, self.queuedValues[0])
|
||||
self.queuedValues.remove(at: 0)
|
||||
self.executingSignal = true
|
||||
} else {
|
||||
currentValue = self.value
|
||||
terminated = self.terminated
|
||||
}
|
||||
OSSpinLockUnlock(&self.lock)
|
||||
|
||||
if terminated {
|
||||
self.subscriber.putNext(currentValue)
|
||||
self.subscriber.putCompletion()
|
||||
} else if nextSignal != nil {
|
||||
let disposable = nextSignal.start(next: { next in
|
||||
self.updateValue(next.0)
|
||||
switch next.1 {
|
||||
case let .Some(value):
|
||||
self.subscriber.putNext(value)
|
||||
case .None:
|
||||
break
|
||||
}
|
||||
}, error: { error in
|
||||
self.subscriber.putError(error)
|
||||
}, completed: {
|
||||
if leftFunction.swap(true) == true {
|
||||
self.headCompleted()
|
||||
}
|
||||
})
|
||||
|
||||
currentDisposable.set(disposable)
|
||||
}
|
||||
|
||||
if leftFunction.swap(true) == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func beginCompletion() {
|
||||
var executingSignal = false
|
||||
let currentValue: T
|
||||
OSSpinLockLock(&self.lock)
|
||||
executingSignal = self.executingSignal
|
||||
self.terminated = true
|
||||
currentValue = self.value
|
||||
OSSpinLockUnlock(&self.lock)
|
||||
|
||||
if !executingSignal {
|
||||
self.subscriber.putNext(currentValue)
|
||||
self.subscriber.putCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.currentDisposable.dispose()
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func reduceLeft<T, E>(_ value: T, generator: @escaping(T, T) -> Signal<(T, Passthrough<T>), E>) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let state = ReduceQueueState(subscriber: subscriber, value: value, generator: generator)
|
||||
state.beginWithDisposable(signal.start(next: { next in
|
||||
state.enqueueNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
state.beginCompletion()
|
||||
}))
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
116
submodules/SSignalKit/SwiftSignalKit/Signal_SideEffects.swift
Normal file
116
submodules/SSignalKit/SwiftSignalKit/Signal_SideEffects.swift
Normal file
@@ -0,0 +1,116 @@
|
||||
import Foundation
|
||||
|
||||
public func beforeNext<T, E, R>(_ f: @escaping(T) -> R) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
let _ = f(next)
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func afterNext<T, E, R>(_ f: @escaping(T) -> R) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
let _ = f(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func beforeStarted<T, E>(_ f: @escaping() -> Void) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
f()
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func beforeCompleted<T, E>(_ f: @escaping() -> Void) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
f()
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func afterCompleted<T, E>(_ f: @escaping() -> Void) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
f()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func afterDisposed<T, E, R>(_ f: @escaping() -> R) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
let disposable = DisposableSet()
|
||||
disposable.add(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
disposable.add(ActionDisposable {
|
||||
let _ = f()
|
||||
})
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func withState<T, E, S>(_ signal: Signal<T, E>, _ initialState: @escaping() -> S, next: @escaping(T, S) -> Void = { _, _ in }, error: @escaping(E, S) -> Void = { _, _ in }, completed: @escaping(S) -> Void = { _ in }, disposed: @escaping(S) -> Void = { _ in }) -> Signal<T, E> {
|
||||
return Signal { subscriber in
|
||||
let state = initialState()
|
||||
let disposable = signal.start(next: { vNext in
|
||||
next(vNext, state)
|
||||
subscriber.putNext(vNext)
|
||||
}, error: { vError in
|
||||
error(vError, state)
|
||||
subscriber.putError(vError)
|
||||
}, completed: {
|
||||
completed(state)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
return ActionDisposable {
|
||||
disposable.dispose()
|
||||
disposed(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
32
submodules/SSignalKit/SwiftSignalKit/Signal_Single.swift
Normal file
32
submodules/SSignalKit/SwiftSignalKit/Signal_Single.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
import Foundation
|
||||
|
||||
public func single<T, E>(_ value: T, _ errorType: E.Type) -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putNext(value)
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public func fail<T, E>(_ valueType: T.Type, _ error: E) -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putError(error)
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public func complete<T, E>(_ valueType: T.Type, _ error: E.Type) -> Signal<T, E> {
|
||||
return Signal<T, E> { subscriber in
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public func never<T, E>(_ valueType: T.Type, _ error: E.Type) -> Signal<T, E> {
|
||||
return Signal { _ in
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
73
submodules/SSignalKit/SwiftSignalKit/Signal_Take.swift
Normal file
73
submodules/SSignalKit/SwiftSignalKit/Signal_Take.swift
Normal file
@@ -0,0 +1,73 @@
|
||||
import Foundation
|
||||
|
||||
public func take<T, E>(_ count: Int) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
let counter = Atomic(value: 0)
|
||||
return signal.start(next: { next in
|
||||
var passthrough = false
|
||||
var complete = false
|
||||
let _ = counter.modify { value in
|
||||
let updatedCount = value + 1
|
||||
passthrough = updatedCount <= count
|
||||
complete = updatedCount == count
|
||||
return updatedCount
|
||||
}
|
||||
if passthrough {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
if complete {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct SignalTakeAction {
|
||||
public let passthrough: Bool
|
||||
public let complete: Bool
|
||||
|
||||
public init(passthrough: Bool, complete: Bool) {
|
||||
self.passthrough = passthrough
|
||||
self.complete = complete
|
||||
}
|
||||
}
|
||||
|
||||
public func take<T, E>(until: @escaping (T) -> SignalTakeAction) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal { subscriber in
|
||||
return signal.start(next: { next in
|
||||
let action = until(next)
|
||||
if action.passthrough {
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
if action.complete {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func last<T, E>(signal: Signal<T, E>) -> Signal<T?, E> {
|
||||
return Signal { subscriber in
|
||||
let value = Atomic<T?>(value: nil)
|
||||
return signal.start(next: { next in
|
||||
let _ = value.swap(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putNext(value.with({ $0 }))
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
122
submodules/SSignalKit/SwiftSignalKit/Signal_Timing.swift
Normal file
122
submodules/SSignalKit/SwiftSignalKit/Signal_Timing.swift
Normal file
@@ -0,0 +1,122 @@
|
||||
import Foundation
|
||||
|
||||
public func delay<T, E>(_ timeout: Double, queue: Queue) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
queue.async {
|
||||
let timer = Timer(timeout: timeout, repeat: false, completion: {
|
||||
disposable.set(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}, queue: queue)
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
timer.invalidate()
|
||||
}
|
||||
})
|
||||
|
||||
timer.start()
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func suspendAwareDelay<T, E>(_ timeout: Double, granularity: Double = 4.0, queue: Queue) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
queue.async {
|
||||
let beginTimestamp = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let startFinalTimer: () -> Void = {
|
||||
let finalTimeout = beginTimestamp + timeout - CFAbsoluteTimeGetCurrent()
|
||||
let timer = Timer(timeout: max(0.0, finalTimeout), repeat: false, completion: {
|
||||
disposable.set(signal.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}, queue: queue)
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
timer.invalidate()
|
||||
}
|
||||
})
|
||||
timer.start()
|
||||
}
|
||||
|
||||
if timeout <= granularity * 1.1 {
|
||||
startFinalTimer()
|
||||
} else {
|
||||
var invalidateImpl: (() -> Void)?
|
||||
let timer = Timer(timeout: granularity, repeat: true, completion: {
|
||||
let currentTimestamp = CFAbsoluteTimeGetCurrent()
|
||||
if beginTimestamp + timeout - granularity * 1.1 <= currentTimestamp {
|
||||
invalidateImpl?()
|
||||
startFinalTimer()
|
||||
}
|
||||
}, queue: queue)
|
||||
|
||||
invalidateImpl = {
|
||||
queue.async {
|
||||
timer.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
invalidateImpl?()
|
||||
})
|
||||
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func timeout<T, E>(_ timeout: Double, queue: Queue, alternate: Signal<T, E>) -> (Signal<T, E>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
let timer = Timer(timeout: timeout, repeat: false, completion: {
|
||||
disposable.set(alternate.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
}, queue: queue)
|
||||
|
||||
disposable.set(signal.start(next: { next in
|
||||
timer.invalidate()
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
timer.invalidate()
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
timer.invalidate()
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
timer.start()
|
||||
|
||||
let disposableSet = DisposableSet()
|
||||
disposableSet.add(ActionDisposable {
|
||||
timer.invalidate()
|
||||
})
|
||||
disposableSet.add(disposable)
|
||||
|
||||
return disposableSet
|
||||
}
|
||||
}
|
||||
}
|
||||
145
submodules/SSignalKit/SwiftSignalKit/Subscriber.swift
Normal file
145
submodules/SSignalKit/SwiftSignalKit/Subscriber.swift
Normal file
@@ -0,0 +1,145 @@
|
||||
import Foundation
|
||||
|
||||
public final class Subscriber<T, E> {
|
||||
private var next: ((T) -> Void)!
|
||||
private var error: ((E) -> Void)!
|
||||
private var completed: (() -> Void)!
|
||||
|
||||
private var lock = pthread_mutex_t()
|
||||
private var terminated = false
|
||||
internal var disposable: Disposable!
|
||||
|
||||
public init(next: ((T) -> Void)! = nil, error: ((E) -> Void)! = nil, completed: (() -> Void)! = nil) {
|
||||
self.next = next
|
||||
self.error = error
|
||||
self.completed = completed
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
var freeDisposable: Disposable?
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if let disposable = self.disposable {
|
||||
freeDisposable = disposable
|
||||
self.disposable = nil
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
if let freeDisposableValue = freeDisposable {
|
||||
withExtendedLifetime(freeDisposableValue, {
|
||||
})
|
||||
freeDisposable = nil
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
internal func assignDisposable(_ disposable: Disposable) {
|
||||
var dispose = false
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if self.terminated {
|
||||
dispose = true
|
||||
} else {
|
||||
self.disposable = disposable
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if dispose {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
internal func markTerminatedWithoutDisposal() {
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.terminated {
|
||||
self.terminated = true
|
||||
self.next = nil
|
||||
self.error = nil
|
||||
self.completed = nil
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
}
|
||||
|
||||
public func putNext(_ next: T) {
|
||||
var action: ((T) -> Void)! = nil
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.terminated {
|
||||
action = self.next
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if action != nil {
|
||||
action(next)
|
||||
}
|
||||
}
|
||||
|
||||
public func putError(_ error: E) {
|
||||
var action: ((E) -> Void)! = nil
|
||||
|
||||
var disposeDisposable: Disposable?
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.terminated {
|
||||
action = self.error
|
||||
self.next = nil
|
||||
self.error = nil
|
||||
self.completed = nil;
|
||||
self.terminated = true
|
||||
disposeDisposable = self.disposable
|
||||
self.disposable = nil
|
||||
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if action != nil {
|
||||
action(error)
|
||||
}
|
||||
|
||||
if let disposeDisposable = disposeDisposable {
|
||||
disposeDisposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func putCompletion() {
|
||||
var action: (() -> Void)! = nil
|
||||
|
||||
var disposeDisposable: Disposable? = nil
|
||||
|
||||
var next: ((T) -> Void)?
|
||||
var error: ((E) -> Void)?
|
||||
var completed: (() -> Void)?
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.terminated {
|
||||
action = self.completed
|
||||
next = self.next
|
||||
self.next = nil
|
||||
error = self.error
|
||||
self.error = nil
|
||||
completed = self.completed
|
||||
self.completed = nil
|
||||
self.terminated = true
|
||||
|
||||
disposeDisposable = self.disposable
|
||||
self.disposable = nil
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if let next = next {
|
||||
withExtendedLifetime(next, {})
|
||||
}
|
||||
if let error = error {
|
||||
withExtendedLifetime(error, {})
|
||||
}
|
||||
if let completed = completed {
|
||||
withExtendedLifetime(completed, {})
|
||||
}
|
||||
|
||||
if action != nil {
|
||||
action()
|
||||
}
|
||||
|
||||
if let disposeDisposable = disposeDisposable {
|
||||
disposeDisposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
23
submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.h
Normal file
23
submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// SwiftSignalKit.h
|
||||
// SwiftSignalKit
|
||||
//
|
||||
// Created by Peter on 10/06/15.
|
||||
// Copyright (c) 2015 Telegram. All rights reserved.
|
||||
//
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
//! Project version number for SwiftSignalKit.
|
||||
FOUNDATION_EXPORT double SwiftSignalKitVersionNumber;
|
||||
|
||||
//! Project version string for SwiftSignalKit.
|
||||
FOUNDATION_EXPORT const unsigned char SwiftSignalKitVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <SwiftSignalKit/PublicHeader.h>
|
||||
|
||||
|
||||
168
submodules/SSignalKit/SwiftSignalKit/ThreadPool.swift
Normal file
168
submodules/SSignalKit/SwiftSignalKit/ThreadPool.swift
Normal file
@@ -0,0 +1,168 @@
|
||||
import Foundation
|
||||
|
||||
public final class ThreadPoolTaskState {
|
||||
public let cancelled = Atomic<Bool>(value: false)
|
||||
}
|
||||
|
||||
public final class ThreadPoolTask {
|
||||
private let state = ThreadPoolTaskState()
|
||||
private let action: (ThreadPoolTaskState) -> ()
|
||||
|
||||
public init(_ action: @escaping(ThreadPoolTaskState) -> ()) {
|
||||
self.action = action
|
||||
}
|
||||
|
||||
func execute() {
|
||||
if !state.cancelled.with { $0 } {
|
||||
self.action(self.state)
|
||||
}
|
||||
}
|
||||
|
||||
public func cancel() {
|
||||
let _ = self.state.cancelled.swap(true)
|
||||
}
|
||||
}
|
||||
|
||||
public final class ThreadPoolQueue : Equatable {
|
||||
private weak var threadPool: ThreadPool?
|
||||
private var tasks: [ThreadPoolTask] = []
|
||||
|
||||
public init(threadPool: ThreadPool) {
|
||||
self.threadPool = threadPool
|
||||
}
|
||||
|
||||
public func addTask(_ task: ThreadPoolTask) {
|
||||
if let threadPool = self.threadPool {
|
||||
threadPool.workOnQueue(self, action: {
|
||||
self.tasks.append(task)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func popFirstTask() -> ThreadPoolTask? {
|
||||
if self.tasks.count != 0 {
|
||||
let task = self.tasks[0];
|
||||
self.tasks.remove(at: 0)
|
||||
return task
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func hasTasks() -> Bool {
|
||||
return self.tasks.count != 0
|
||||
}
|
||||
}
|
||||
|
||||
public func ==(lhs: ThreadPoolQueue, rhs: ThreadPoolQueue) -> Bool {
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
@objc public final class ThreadPool: NSObject {
|
||||
private var threads: [Thread] = []
|
||||
private var queues: [ThreadPoolQueue] = []
|
||||
private var takenQueues: [ThreadPoolQueue] = []
|
||||
private var mutex: pthread_mutex_t
|
||||
private var condition: pthread_cond_t
|
||||
|
||||
@objc class func threadEntryPoint(_ threadPool: ThreadPool) {
|
||||
var queue: ThreadPoolQueue!
|
||||
|
||||
while (true) {
|
||||
var task: ThreadPoolTask!
|
||||
|
||||
pthread_mutex_lock(&threadPool.mutex);
|
||||
|
||||
if queue != nil {
|
||||
if let index = threadPool.takenQueues.index(of: queue) {
|
||||
threadPool.takenQueues.remove(at: index)
|
||||
}
|
||||
|
||||
if queue.hasTasks() {
|
||||
threadPool.queues.append(queue);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
while threadPool.queues.count == 0 {
|
||||
pthread_cond_wait(&threadPool.condition, &threadPool.mutex);
|
||||
}
|
||||
|
||||
if threadPool.queues.count != 0 {
|
||||
queue = threadPool.queues[0]
|
||||
}
|
||||
|
||||
if queue != nil {
|
||||
task = queue.popFirstTask()
|
||||
threadPool.takenQueues.append(queue)
|
||||
|
||||
if let index = threadPool.queues.index(of: queue) {
|
||||
threadPool.queues.remove(at: index)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&threadPool.mutex);
|
||||
|
||||
if task != nil {
|
||||
autoreleasepool {
|
||||
task.execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(threadCount: Int, threadPriority: Double) {
|
||||
assert(threadCount > 0, "threadCount < 0")
|
||||
|
||||
self.mutex = pthread_mutex_t()
|
||||
self.condition = pthread_cond_t()
|
||||
pthread_mutex_init(&self.mutex, nil)
|
||||
pthread_cond_init(&self.condition, nil)
|
||||
|
||||
super.init()
|
||||
|
||||
for _ in 0 ..< threadCount {
|
||||
let thread = Thread(target: ThreadPool.self, selector: #selector(ThreadPool.threadEntryPoint(_:)), object: self)
|
||||
thread.threadPriority = threadPriority
|
||||
self.threads.append(thread)
|
||||
thread.start()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.mutex)
|
||||
pthread_cond_destroy(&self.condition)
|
||||
}
|
||||
|
||||
public func addTask(_ task: ThreadPoolTask) {
|
||||
let tempQueue = self.nextQueue()
|
||||
tempQueue.addTask(task)
|
||||
}
|
||||
|
||||
fileprivate func workOnQueue(_ queue: ThreadPoolQueue, action: () -> ()) {
|
||||
pthread_mutex_lock(&self.mutex)
|
||||
action()
|
||||
if !self.queues.contains(queue) && !self.takenQueues.contains(queue) {
|
||||
self.queues.append(queue)
|
||||
}
|
||||
pthread_cond_broadcast(&self.condition)
|
||||
pthread_mutex_unlock(&self.mutex)
|
||||
}
|
||||
|
||||
public func nextQueue() -> ThreadPoolQueue {
|
||||
return ThreadPoolQueue(threadPool: self)
|
||||
}
|
||||
|
||||
public func isCurrentThreadInPool() -> Bool {
|
||||
let currentThread = Thread.current
|
||||
for thread in self.threads {
|
||||
if currentThread.isEqual(thread) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
52
submodules/SSignalKit/SwiftSignalKit/Timer.swift
Normal file
52
submodules/SSignalKit/SwiftSignalKit/Timer.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
import Foundation
|
||||
|
||||
public final class Timer {
|
||||
private let timer = Atomic<DispatchSourceTimer?>(value: nil)
|
||||
private let timeout: Double
|
||||
private let `repeat`: Bool
|
||||
private let completion: () -> Void
|
||||
private let queue: Queue
|
||||
|
||||
public init(timeout: Double, `repeat`: Bool, completion: @escaping() -> Void, queue: Queue) {
|
||||
self.timeout = timeout
|
||||
self.`repeat` = `repeat`
|
||||
self.completion = completion
|
||||
self.queue = queue
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.invalidate()
|
||||
}
|
||||
|
||||
public func start() {
|
||||
let timer = DispatchSource.makeTimerSource(queue: self.queue.queue)
|
||||
timer.setEventHandler(handler: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.completion()
|
||||
if !strongSelf.`repeat` {
|
||||
strongSelf.invalidate()
|
||||
}
|
||||
}
|
||||
})
|
||||
let _ = self.timer.modify { _ in
|
||||
return timer
|
||||
}
|
||||
|
||||
if self.`repeat` {
|
||||
let time: DispatchTime = DispatchTime.now() + self.timeout
|
||||
timer.scheduleRepeating(deadline: time, interval: self.timeout)
|
||||
} else {
|
||||
let time: DispatchTime = DispatchTime.now() + self.timeout
|
||||
timer.scheduleOneshot(deadline: time)
|
||||
}
|
||||
|
||||
timer.resume()
|
||||
}
|
||||
|
||||
public func invalidate() {
|
||||
let _ = self.timer.modify { timer in
|
||||
timer?.cancel()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
39
submodules/SSignalKit/SwiftSignalKit/ValuePipe.swift
Normal file
39
submodules/SSignalKit/SwiftSignalKit/ValuePipe.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
import Foundation
|
||||
|
||||
public final class ValuePipe<T> {
|
||||
private let subscribers = Atomic(value: Bag<(T) -> Void>())
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func signal() -> Signal<T, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
let index = strongSelf.subscribers.with { value -> Bag<T>.Index in
|
||||
return value.add { next in
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
}
|
||||
|
||||
return ActionDisposable { [weak strongSelf] in
|
||||
if let strongSelf = strongSelf {
|
||||
strongSelf.subscribers.with { value -> Void in
|
||||
value.remove(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func putNext(_ next: T) {
|
||||
let items = self.subscribers.with { value -> [(T) -> Void] in
|
||||
return value.copyItems()
|
||||
}
|
||||
for f in items {
|
||||
f(next)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user