2019-11-14 01:14:35 +04:00

140 lines
4.2 KiB
Swift

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)
}
}
}
}