This commit is contained in:
DDIsFriend
2023-08-18 17:28:57 +08:00
commit f0e8a1709d
4282 changed files with 192396 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
//
// AnonymousDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 2/15/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents an Action-based disposable.
///
/// When dispose method is called, disposal action will be dereferenced.
private final class AnonymousDisposable : DisposeBase, Cancelable {
public typealias DisposeAction = () -> Void
private let disposed = AtomicInt(0)
private var disposeAction: DisposeAction?
/// - returns: Was resource disposed.
public var isDisposed: Bool {
isFlagSet(self.disposed, 1)
}
/// Constructs a new disposable with the given action used for disposal.
///
/// - parameter disposeAction: Disposal action which will be run upon calling `dispose`.
private init(_ disposeAction: @escaping DisposeAction) {
self.disposeAction = disposeAction
super.init()
}
// Non-deprecated version of the constructor, used by `Disposables.create(with:)`
fileprivate init(disposeAction: @escaping DisposeAction) {
self.disposeAction = disposeAction
super.init()
}
/// Calls the disposal action if and only if the current instance hasn't been disposed yet.
///
/// After invoking disposal action, disposal action will be dereferenced.
fileprivate func dispose() {
if fetchOr(self.disposed, 1) == 0 {
if let action = self.disposeAction {
self.disposeAction = nil
action()
}
}
}
}
extension Disposables {
/// Constructs a new disposable with the given action used for disposal.
///
/// - parameter dispose: Disposal action which will be run upon calling `dispose`.
public static func create(with dispose: @escaping () -> Void) -> Cancelable {
AnonymousDisposable(disposeAction: dispose)
}
}

View File

@@ -0,0 +1,53 @@
//
// BinaryDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 6/12/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents two disposable resources that are disposed together.
private final class BinaryDisposable : DisposeBase, Cancelable {
private let disposed = AtomicInt(0)
// state
private var disposable1: Disposable?
private var disposable2: Disposable?
/// - returns: Was resource disposed.
var isDisposed: Bool {
isFlagSet(self.disposed, 1)
}
/// Constructs new binary disposable from two disposables.
///
/// - parameter disposable1: First disposable
/// - parameter disposable2: Second disposable
init(_ disposable1: Disposable, _ disposable2: Disposable) {
self.disposable1 = disposable1
self.disposable2 = disposable2
super.init()
}
/// Calls the disposal action if and only if the current instance hasn't been disposed yet.
///
/// After invoking disposal action, disposal action will be dereferenced.
func dispose() {
if fetchOr(self.disposed, 1) == 0 {
self.disposable1?.dispose()
self.disposable2?.dispose()
self.disposable1 = nil
self.disposable2 = nil
}
}
}
extension Disposables {
/// Creates a disposable with the given disposables.
public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
BinaryDisposable(disposable1, disposable2)
}
}

View File

@@ -0,0 +1,33 @@
//
// BooleanDisposable.swift
// RxSwift
//
// Created by Junior B. on 10/29/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents a disposable resource that can be checked for disposal status.
public final class BooleanDisposable : Cancelable {
internal static let BooleanDisposableTrue = BooleanDisposable(isDisposed: true)
private var disposed = false
/// Initializes a new instance of the `BooleanDisposable` class
public init() {
}
/// Initializes a new instance of the `BooleanDisposable` class with given value
public init(isDisposed: Bool) {
self.disposed = isDisposed
}
/// - returns: Was resource disposed.
public var isDisposed: Bool {
self.disposed
}
/// Sets the status to disposed, which can be observer through the `isDisposed` property.
public func dispose() {
self.disposed = true
}
}

View File

@@ -0,0 +1,147 @@
//
// CompositeDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 2/20/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents a group of disposable resources that are disposed together.
public final class CompositeDisposable : DisposeBase, Cancelable {
/// Key used to remove disposable from composite disposable
public struct DisposeKey {
fileprivate let key: BagKey
fileprivate init(key: BagKey) {
self.key = key
}
}
private var lock = SpinLock()
// state
private var disposables: Bag<Disposable>? = Bag()
public var isDisposed: Bool {
self.lock.performLocked { self.disposables == nil }
}
public override init() {
}
/// Initializes a new instance of composite disposable with the specified number of disposables.
public init(_ disposable1: Disposable, _ disposable2: Disposable) {
// This overload is here to make sure we are using optimized version up to 4 arguments.
_ = self.disposables!.insert(disposable1)
_ = self.disposables!.insert(disposable2)
}
/// Initializes a new instance of composite disposable with the specified number of disposables.
public init(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable) {
// This overload is here to make sure we are using optimized version up to 4 arguments.
_ = self.disposables!.insert(disposable1)
_ = self.disposables!.insert(disposable2)
_ = self.disposables!.insert(disposable3)
}
/// Initializes a new instance of composite disposable with the specified number of disposables.
public init(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable, _ disposable4: Disposable, _ disposables: Disposable...) {
// This overload is here to make sure we are using optimized version up to 4 arguments.
_ = self.disposables!.insert(disposable1)
_ = self.disposables!.insert(disposable2)
_ = self.disposables!.insert(disposable3)
_ = self.disposables!.insert(disposable4)
for disposable in disposables {
_ = self.disposables!.insert(disposable)
}
}
/// Initializes a new instance of composite disposable with the specified number of disposables.
public init(disposables: [Disposable]) {
for disposable in disposables {
_ = self.disposables!.insert(disposable)
}
}
/**
Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
- parameter disposable: Disposable to add.
- returns: Key that can be used to remove disposable from composite disposable. In case dispose bag was already
disposed `nil` will be returned.
*/
public func insert(_ disposable: Disposable) -> DisposeKey? {
let key = self._insert(disposable)
if key == nil {
disposable.dispose()
}
return key
}
private func _insert(_ disposable: Disposable) -> DisposeKey? {
self.lock.performLocked {
let bagKey = self.disposables?.insert(disposable)
return bagKey.map(DisposeKey.init)
}
}
/// - returns: Gets the number of disposables contained in the `CompositeDisposable`.
public var count: Int {
self.lock.performLocked { self.disposables?.count ?? 0 }
}
/// Removes and disposes the disposable identified by `disposeKey` from the CompositeDisposable.
///
/// - parameter disposeKey: Key used to identify disposable to be removed.
public func remove(for disposeKey: DisposeKey) {
self._remove(for: disposeKey)?.dispose()
}
private func _remove(for disposeKey: DisposeKey) -> Disposable? {
self.lock.performLocked { self.disposables?.removeKey(disposeKey.key) }
}
/// Disposes all disposables in the group and removes them from the group.
public func dispose() {
if let disposables = self._dispose() {
disposeAll(in: disposables)
}
}
private func _dispose() -> Bag<Disposable>? {
self.lock.performLocked {
let current = self.disposables
self.disposables = nil
return current
}
}
}
extension Disposables {
/// Creates a disposable with the given disposables.
public static func create(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable) -> Cancelable {
CompositeDisposable(disposable1, disposable2, disposable3)
}
/// Creates a disposable with the given disposables.
public static func create(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable, _ disposables: Disposable ...) -> Cancelable {
var disposables = disposables
disposables.append(disposable1)
disposables.append(disposable2)
disposables.append(disposable3)
return CompositeDisposable(disposables: disposables)
}
/// Creates a disposable with the given disposables.
public static func create(_ disposables: [Disposable]) -> Cancelable {
switch disposables.count {
case 2:
return Disposables.create(disposables[0], disposables[1])
default:
return CompositeDisposable(disposables: disposables)
}
}
}

View File

@@ -0,0 +1,13 @@
//
// Disposables.swift
// RxSwift
//
// Created by Mohsen Ramezanpoor on 01/08/2016.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
/// A collection of utility methods for common disposable operations.
public struct Disposables {
private init() {}
}

View File

@@ -0,0 +1,144 @@
//
// DisposeBag.swift
// RxSwift
//
// Created by Krunoslav Zaher on 3/25/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Disposable {
/// Adds `self` to `bag`
///
/// - parameter bag: `DisposeBag` to add `self` to.
public func disposed(by bag: DisposeBag) {
bag.insert(self)
}
}
/**
Thread safe bag that disposes added disposables on `deinit`.
This returns ARC (RAII) like resource management to `RxSwift`.
In case contained disposables need to be disposed, just put a different dispose bag
or create a new one in its place.
self.existingDisposeBag = DisposeBag()
In case explicit disposal is necessary, there is also `CompositeDisposable`.
*/
public final class DisposeBag: DisposeBase {
private var lock = SpinLock()
// state
private var disposables = [Disposable]()
private var isDisposed = false
/// Constructs new empty dispose bag.
public override init() {
super.init()
}
/// Adds `disposable` to be disposed when dispose bag is being deinited.
///
/// - parameter disposable: Disposable to add.
public func insert(_ disposable: Disposable) {
self._insert(disposable)?.dispose()
}
private func _insert(_ disposable: Disposable) -> Disposable? {
self.lock.performLocked {
if self.isDisposed {
return disposable
}
self.disposables.append(disposable)
return nil
}
}
/// This is internal on purpose, take a look at `CompositeDisposable` instead.
private func dispose() {
let oldDisposables = self._dispose()
for disposable in oldDisposables {
disposable.dispose()
}
}
private func _dispose() -> [Disposable] {
self.lock.performLocked {
let disposables = self.disposables
self.disposables.removeAll(keepingCapacity: false)
self.isDisposed = true
return disposables
}
}
deinit {
self.dispose()
}
}
extension DisposeBag {
/// Convenience init allows a list of disposables to be gathered for disposal.
public convenience init(disposing disposables: Disposable...) {
self.init()
self.disposables += disposables
}
/// Convenience init which utilizes a function builder to let you pass in a list of
/// disposables to make a DisposeBag of.
public convenience init(@DisposableBuilder builder: () -> [Disposable]) {
self.init(disposing: builder())
}
/// Convenience init allows an array of disposables to be gathered for disposal.
public convenience init(disposing disposables: [Disposable]) {
self.init()
self.disposables += disposables
}
/// Convenience function allows a list of disposables to be gathered for disposal.
public func insert(_ disposables: Disposable...) {
self.insert(disposables)
}
/// Convenience function allows a list of disposables to be gathered for disposal.
public func insert(@DisposableBuilder builder: () -> [Disposable]) {
self.insert(builder())
}
/// Convenience function allows an array of disposables to be gathered for disposal.
public func insert(_ disposables: [Disposable]) {
self.lock.performLocked {
if self.isDisposed {
disposables.forEach { $0.dispose() }
} else {
self.disposables += disposables
}
}
}
/// A function builder accepting a list of Disposables and returning them as an array.
#if swift(>=5.4)
@resultBuilder
public struct DisposableBuilder {
public static func buildBlock(_ disposables: Disposable...) -> [Disposable] {
return disposables
}
}
#else
@_functionBuilder
public struct DisposableBuilder {
public static func buildBlock(_ disposables: Disposable...) -> [Disposable] {
return disposables
}
}
#endif
}

View File

@@ -0,0 +1,22 @@
//
// DisposeBase.swift
// RxSwift
//
// Created by Krunoslav Zaher on 4/4/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Base class for all disposables.
public class DisposeBase {
init() {
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
}
deinit {
#if TRACE_RESOURCES
_ = Resources.decrementTotal()
#endif
}
}

View File

@@ -0,0 +1,30 @@
//
// NopDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 2/15/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents a disposable that does nothing on disposal.
///
/// Nop = No Operation
private struct NopDisposable : Disposable {
fileprivate static let noOp: Disposable = NopDisposable()
private init() {
}
/// Does nothing.
public func dispose() {
}
}
extension Disposables {
/**
Creates a disposable that does nothing on disposal.
*/
static public func create() -> Disposable { NopDisposable.noOp }
}

View File

@@ -0,0 +1,112 @@
//
// RefCountDisposable.swift
// RxSwift
//
// Created by Junior B. on 10/29/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents a disposable resource that only disposes its underlying disposable resource when all dependent disposable objects have been disposed.
public final class RefCountDisposable : DisposeBase, Cancelable {
private var lock = SpinLock()
private var disposable = nil as Disposable?
private var primaryDisposed = false
private var count = 0
/// - returns: Was resource disposed.
public var isDisposed: Bool {
self.lock.performLocked { self.disposable == nil }
}
/// Initializes a new instance of the `RefCountDisposable`.
public init(disposable: Disposable) {
self.disposable = disposable
super.init()
}
/**
Holds a dependent disposable that when disposed decreases the refcount on the underlying disposable.
When getter is called, a dependent disposable contributing to the reference count that manages the underlying disposable's lifetime is returned.
*/
public func retain() -> Disposable {
self.lock.performLocked {
if self.disposable != nil {
do {
_ = try incrementChecked(&self.count)
} catch {
rxFatalError("RefCountDisposable increment failed")
}
return RefCountInnerDisposable(self)
} else {
return Disposables.create()
}
}
}
/// Disposes the underlying disposable only when all dependent disposables have been disposed.
public func dispose() {
let oldDisposable: Disposable? = self.lock.performLocked {
if let oldDisposable = self.disposable, !self.primaryDisposed {
self.primaryDisposed = true
if self.count == 0 {
self.disposable = nil
return oldDisposable
}
}
return nil
}
if let disposable = oldDisposable {
disposable.dispose()
}
}
fileprivate func release() {
let oldDisposable: Disposable? = self.lock.performLocked {
if let oldDisposable = self.disposable {
do {
_ = try decrementChecked(&self.count)
} catch {
rxFatalError("RefCountDisposable decrement on release failed")
}
guard self.count >= 0 else {
rxFatalError("RefCountDisposable counter is lower than 0")
}
if self.primaryDisposed && self.count == 0 {
self.disposable = nil
return oldDisposable
}
}
return nil
}
if let disposable = oldDisposable {
disposable.dispose()
}
}
}
internal final class RefCountInnerDisposable: DisposeBase, Disposable
{
private let parent: RefCountDisposable
private let isDisposed = AtomicInt(0)
init(_ parent: RefCountDisposable) {
self.parent = parent
super.init()
}
internal func dispose()
{
if fetchOr(self.isDisposed, 1) == 0 {
self.parent.release()
}
}
}

View File

@@ -0,0 +1,50 @@
//
// ScheduledDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 6/13/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
private let disposeScheduledDisposable: (ScheduledDisposable) -> Disposable = { sd in
sd.disposeInner()
return Disposables.create()
}
/// Represents a disposable resource whose disposal invocation will be scheduled on the specified scheduler.
public final class ScheduledDisposable : Cancelable {
public let scheduler: ImmediateSchedulerType
private let disposed = AtomicInt(0)
// state
private var disposable: Disposable?
/// - returns: Was resource disposed.
public var isDisposed: Bool {
isFlagSet(self.disposed, 1)
}
/**
Initializes a new instance of the `ScheduledDisposable` that uses a `scheduler` on which to dispose the `disposable`.
- parameter scheduler: Scheduler where the disposable resource will be disposed on.
- parameter disposable: Disposable resource to dispose on the given scheduler.
*/
public init(scheduler: ImmediateSchedulerType, disposable: Disposable) {
self.scheduler = scheduler
self.disposable = disposable
}
/// Disposes the wrapped disposable on the provided scheduler.
public func dispose() {
_ = self.scheduler.schedule(self, action: disposeScheduledDisposable)
}
func disposeInner() {
if fetchOr(self.disposed, 1) == 0 {
self.disposable!.dispose()
self.disposable = nil
}
}
}

View File

@@ -0,0 +1,73 @@
//
// SerialDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 3/12/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
public final class SerialDisposable : DisposeBase, Cancelable {
private var lock = SpinLock()
// state
private var current = nil as Disposable?
private var disposed = false
/// - returns: Was resource disposed.
public var isDisposed: Bool {
self.disposed
}
/// Initializes a new instance of the `SerialDisposable`.
override public init() {
super.init()
}
/**
Gets or sets the underlying disposable.
Assigning this property disposes the previous disposable object.
If the `SerialDisposable` has already been disposed, assignment to this property causes immediate disposal of the given disposable object.
*/
public var disposable: Disposable {
get {
self.lock.performLocked {
self.current ?? Disposables.create()
}
}
set (newDisposable) {
let disposable: Disposable? = self.lock.performLocked {
if self.isDisposed {
return newDisposable
}
else {
let toDispose = self.current
self.current = newDisposable
return toDispose
}
}
if let disposable = disposable {
disposable.dispose()
}
}
}
/// Disposes the underlying disposable as well as all future replacements.
public func dispose() {
self._dispose()?.dispose()
}
private func _dispose() -> Disposable? {
self.lock.performLocked {
guard !self.isDisposed else { return nil }
self.disposed = true
let current = self.current
self.current = nil
return current
}
}
}

View File

@@ -0,0 +1,72 @@
//
// SingleAssignmentDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 2/15/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/**
Represents a disposable resource which only allows a single assignment of its underlying disposable resource.
If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an exception.
*/
public final class SingleAssignmentDisposable : DisposeBase, Cancelable {
private struct DisposeState: OptionSet {
let rawValue: Int32
static let disposed = DisposeState(rawValue: 1 << 0)
static let disposableSet = DisposeState(rawValue: 1 << 1)
}
// state
private let state = AtomicInt(0)
private var disposable = nil as Disposable?
/// - returns: A value that indicates whether the object is disposed.
public var isDisposed: Bool {
isFlagSet(self.state, DisposeState.disposed.rawValue)
}
/// Initializes a new instance of the `SingleAssignmentDisposable`.
public override init() {
super.init()
}
/// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
///
/// **Throws exception if the `SingleAssignmentDisposable` has already been assigned to.**
public func setDisposable(_ disposable: Disposable) {
self.disposable = disposable
let previousState = fetchOr(self.state, DisposeState.disposableSet.rawValue)
if (previousState & DisposeState.disposableSet.rawValue) != 0 {
rxFatalError("oldState.disposable != nil")
}
if (previousState & DisposeState.disposed.rawValue) != 0 {
disposable.dispose()
self.disposable = nil
}
}
/// Disposes the underlying disposable.
public func dispose() {
let previousState = fetchOr(self.state, DisposeState.disposed.rawValue)
if (previousState & DisposeState.disposed.rawValue) != 0 {
return
}
if (previousState & DisposeState.disposableSet.rawValue) != 0 {
guard let disposable = self.disposable else {
rxFatalError("Disposable not set")
}
disposable.dispose()
self.disposable = nil
}
}
}

View File

@@ -0,0 +1,21 @@
//
// SubscriptionDisposable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 10/25/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
struct SubscriptionDisposable<T: SynchronizedUnsubscribeType> : Disposable {
private let key: T.DisposeKey
private weak var owner: T?
init(owner: T, key: T.DisposeKey) {
self.owner = owner
self.key = key
}
func dispose() {
self.owner?.synchronizedUnsubscribe(self.key)
}
}