mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
[WIP] Disposable debugging
This commit is contained in:
@@ -4,6 +4,32 @@ public protocol Disposable: AnyObject {
|
||||
func dispose()
|
||||
}
|
||||
|
||||
public final class StrictDisposable: Disposable {
|
||||
private let disposable: Disposable
|
||||
private let isDisposed = Atomic<Bool>(value: false)
|
||||
|
||||
public init(_ disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if DEBUG
|
||||
assert(self.isDisposed.with({ $0 }))
|
||||
#endif
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let _ = self.isDisposed.swap(true)
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public extension Disposable {
|
||||
func strict() -> Disposable {
|
||||
return StrictDisposable(self)
|
||||
}
|
||||
}
|
||||
|
||||
final class _EmptyDisposable: Disposable {
|
||||
func dispose() {
|
||||
}
|
||||
|
||||
@@ -23,18 +23,37 @@ public func |> <T, U>(value: T, function: ((T) -> U)) -> U {
|
||||
return function(value)
|
||||
}
|
||||
|
||||
private final class SubscriberDisposable<T, E> : Disposable {
|
||||
private final class SubscriberDisposable<T, E>: Disposable, CustomStringConvertible {
|
||||
private let subscriber: Subscriber<T, E>
|
||||
private let disposable: Disposable
|
||||
|
||||
init(subscriber: Subscriber<T, E>, disposable: Disposable) {
|
||||
private var lock = pthread_mutex_t()
|
||||
private var disposable: Disposable?
|
||||
|
||||
init(subscriber: Subscriber<T, E>, disposable: Disposable?) {
|
||||
self.subscriber = subscriber
|
||||
self.disposable = disposable
|
||||
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.lock)
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
subscriber.markTerminatedWithoutDisposal()
|
||||
disposable.dispose()
|
||||
self.subscriber.markTerminatedWithoutDisposal()
|
||||
|
||||
var disposeItem: Disposable?
|
||||
pthread_mutex_lock(&self.lock)
|
||||
disposeItem = self.disposable
|
||||
self.disposable = nil
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
disposeItem?.dispose()
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return "SubscriberDisposable { disposable: \(self.disposable == nil ? "nil" : "hasValue") }"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import Foundation
|
||||
|
||||
public final class Subscriber<T, E> {
|
||||
#if DEBUG
|
||||
// Signals keep themselves in memory until terminated (dispose, putError, putCompletion)
|
||||
private final class LiveSubscribers {
|
||||
var dict: [ObjectIdentifier: AnyObject] = [:]
|
||||
}
|
||||
private let liveSubscribers = Atomic<LiveSubscribers>(value: LiveSubscribers())
|
||||
#endif
|
||||
|
||||
public final class Subscriber<T, E>: CustomStringConvertible {
|
||||
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!
|
||||
internal var disposable: Disposable?
|
||||
|
||||
public init(next: ((T) -> Void)! = nil, error: ((E) -> Void)! = nil, completed: (() -> Void)! = nil) {
|
||||
self.next = next
|
||||
@@ -16,6 +24,10 @@ public final class Subscriber<T, E> {
|
||||
pthread_mutex_init(&self.lock, nil)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return "Subscriber { next: \(self.next == nil ? "nil" : "hasValue"), error: \(self.error == nil ? "nil" : "hasValue"), completed: \(self.completed == nil ? "nil" : "hasValue"), disposable: \(self.disposable == nil ? "nil" : "hasValue"), terminated: \(self.terminated) }"
|
||||
}
|
||||
|
||||
deinit {
|
||||
var freeDisposable: Disposable?
|
||||
pthread_mutex_lock(&self.lock)
|
||||
@@ -34,6 +46,12 @@ public final class Subscriber<T, E> {
|
||||
}
|
||||
|
||||
internal func assignDisposable(_ disposable: Disposable) {
|
||||
#if DEBUG
|
||||
liveSubscribers.with { impl in
|
||||
//let _ = impl.dict[ObjectIdentifier(self)] = self
|
||||
}
|
||||
#endif
|
||||
|
||||
var dispose = false
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if self.terminated {
|
||||
@@ -49,14 +67,33 @@ public final class Subscriber<T, E> {
|
||||
}
|
||||
|
||||
internal func markTerminatedWithoutDisposal() {
|
||||
var freeDisposable: Disposable?
|
||||
|
||||
pthread_mutex_lock(&self.lock)
|
||||
if !self.terminated {
|
||||
self.terminated = true
|
||||
self.next = nil
|
||||
self.error = nil
|
||||
self.completed = nil
|
||||
|
||||
if let disposable = self.disposable {
|
||||
freeDisposable = disposable
|
||||
self.disposable = nil
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
if let freeDisposableValue = freeDisposable {
|
||||
withExtendedLifetime(freeDisposableValue, {
|
||||
})
|
||||
freeDisposable = nil
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
liveSubscribers.with { impl in
|
||||
let _ = impl.dict.removeValue(forKey: ObjectIdentifier(self))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public func putNext(_ next: T) {
|
||||
@@ -86,7 +123,6 @@ public final class Subscriber<T, E> {
|
||||
self.terminated = true
|
||||
disposeDisposable = self.disposable
|
||||
self.disposable = nil
|
||||
|
||||
}
|
||||
pthread_mutex_unlock(&self.lock)
|
||||
|
||||
@@ -97,6 +133,12 @@ public final class Subscriber<T, E> {
|
||||
if let disposeDisposable = disposeDisposable {
|
||||
disposeDisposable.dispose()
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
liveSubscribers.with { impl in
|
||||
let _ = impl.dict.removeValue(forKey: ObjectIdentifier(self))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public func putCompletion() {
|
||||
@@ -141,5 +183,11 @@ public final class Subscriber<T, E> {
|
||||
if let disposeDisposable = disposeDisposable {
|
||||
disposeDisposable.dispose()
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
liveSubscribers.with { impl in
|
||||
let _ = impl.dict.removeValue(forKey: ObjectIdentifier(self))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user