Facilitates cleanup of arbitrary resources, handling multi-ownership concerns.
Scope
is IDisposable
and initialized with a callback that is called on dispose
. Scope
also exposes a transfer
method when ownership needs to be transferred.
let scope = Scope {
print("Disposing!")
}
let transferred = scope.transfer()
scope.dispose() // Does nothing
transferred.dispose() // Prints 'Disposing!'
Consider an object that generates data, lets call this the generator. Consider an object that cares about that data, and wants to subscribe to changes, lets call this the subscriber.
Lets say that the generator has a finite lifetime that may or may not end before with the subscribers lifetime ends.
If we're implementing the generator to have references to all subscribers so that it can execute a callback on a data change, then we need to clean that up when the generator goes out of scope. If a subscriber needs to go out of scope, it should clean itself up from the generator. Now, lets do this without injecting the subscriber with any dependent knowledge of the generator other than a subscribe method.
In this example, Subscriber
is private to Generator
, and Consumer
is the object that subscribes and consumes the data.
class Consumer : IDisposable
{
public init(_ generator: Generator) {
_scope = try! generator.subscribe { _ in
print("Do things with data")
}
}
public func dispose() {
_scope.dispose()
}
private var _scope: Scope
}
class Generator : IDisposable
{
public init() {
_subscribers = Array<Subscriber>()
}
public func dispose() {
if (_subscribers == nil) {
return
}
for subscriber in _subscribers! {
_ = subscriber.scope?.transfer()
}
_subscribers = nil
}
public func subscribe(_ callback: @escaping (Data) -> ()) throws -> Scope {
if (_subscribers == nil) {
throw ObjectDisposedException.ObjectDisposed
}
let sub = Subscriber(callback)
let scope = Scope {
self._subscribers = self._subscribers!.filter { $0 !== sub }
}
sub.scope = scope
_subscribers?.append(sub)
return scope
}
private var _subscribers: Array<Subscriber>?
}
private class Subscriber
{
public var callback: (Data) -> ()
public var scope: Scope?
public init(_ callback: @escaping (Data) -> ()) {
self.callback = callback
}
}
link |
Stars: 0 |
Last commit: 3 years ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics