Renamed ColdSignal to Source. Remains to be seen if this is a good idea.

This commit is contained in:
Tyler Cloutier 2016-11-20 22:52:38 -08:00
parent 09e270d688
commit cb9f2411c5
4 changed files with 71 additions and 72 deletions

View File

@ -9,7 +9,7 @@
/* Begin PBXBuildFile section */
DC30FA8A1DDAFFED00C2CC7F /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC30FA891DDAFFED00C2CC7F /* Error.swift */; };
OBJ_26 /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* Bag.swift */; };
OBJ_27 /* ColdSignal.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* ColdSignal.swift */; };
OBJ_27 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* Source.swift */; };
OBJ_28 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Disposable.swift */; };
OBJ_29 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* Event.swift */; };
OBJ_30 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* Observer.swift */; };
@ -30,7 +30,7 @@
/* Begin PBXFileReference section */
DC30FA891DDAFFED00C2CC7F /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
OBJ_10 /* ColdSignal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColdSignal.swift; sourceTree = "<group>"; };
OBJ_10 /* Source.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Source.swift; sourceTree = "<group>"; };
OBJ_11 /* Disposable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = "<group>"; };
OBJ_12 /* Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = "<group>"; };
OBJ_13 /* Observer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Observer.swift; sourceTree = "<group>"; };
@ -87,7 +87,7 @@
name = Products;
sourceTree = BUILT_PRODUCTS_DIR;
};
OBJ_5 /* */ = {
OBJ_5 = {
isa = PBXGroup;
children = (
OBJ_6 /* Package.swift */,
@ -95,7 +95,6 @@
OBJ_15 /* Tests */,
OBJ_18 /* Products */,
);
name = "";
sourceTree = "<group>";
};
OBJ_7 /* Sources */ = {
@ -110,11 +109,11 @@
isa = PBXGroup;
children = (
OBJ_9 /* Bag.swift */,
OBJ_10 /* ColdSignal.swift */,
OBJ_11 /* Disposable.swift */,
OBJ_12 /* Event.swift */,
OBJ_13 /* Observer.swift */,
OBJ_14 /* Signal.swift */,
OBJ_10 /* Source.swift */,
DC30FA891DDAFFED00C2CC7F /* Error.swift */,
);
name = Reflex;
@ -172,7 +171,7 @@
knownRegions = (
en,
);
mainGroup = OBJ_5 /* */;
mainGroup = OBJ_5;
productRefGroup = OBJ_18 /* Products */;
projectDirPath = "";
projectRoot = "";
@ -189,7 +188,7 @@
buildActionMask = 0;
files = (
OBJ_26 /* Bag.swift in Sources */,
OBJ_27 /* ColdSignal.swift in Sources */,
OBJ_27 /* Source.swift in Sources */,
OBJ_28 /* Disposable.swift in Sources */,
OBJ_29 /* Event.swift in Sources */,
OBJ_30 /* Observer.swift in Sources */,

View File

@ -10,7 +10,7 @@ import Foundation
/// A CiruitBreaker optionally holds a strong reference to either a
/// `Signal` or a `ColdSignal` until a terminating event is
/// `Signal` or a `Source` until a terminating event is
/// received. At such time, it delivers the event and then
/// removes its reference. In so doing, it "breaks the circuit"
/// between the signal, the handler, and the input observer.
@ -18,7 +18,7 @@ import Foundation
class CircuitBreaker<Value, Error: Swift.Error> {
private var signal: Signal<Value, Error>? = nil
private var coldSignal: ColdSignal<Value, Error>? = nil
private var source: Source<Value, Error>? = nil
fileprivate var action: Observer<Value, Error>.Action! = nil
/// Holds a strong reference to a `Signal` until a
@ -37,18 +37,18 @@ class CircuitBreaker<Value, Error: Swift.Error> {
}
}
/// Holds a strong reference to a `ColdSignal` until a
/// Holds a strong reference to a `Source` until a
/// terminating event is received.
init(holding coldSignal: ColdSignal<Value, Error>?) {
self.coldSignal = coldSignal
init(holding source: Source<Value, Error>?) {
self.source = source
self.action = { [weak self] event in
// If event is terminating dispose of the handlerDisposable.
self?.coldSignal?.observers.forEach { observer in
self?.source?.observers.forEach { observer in
observer.send(event)
}
if event.isTerminating {
self?.coldSignal = nil
self?.source = nil
}
}
}

View File

@ -145,7 +145,7 @@ public protocol SignalType {
/// then `NoError` can be used.
associatedtype Error: Swift.Error
/// The exposed raw signal that underlies the ColdSignalType
/// The exposed raw signal that underlies the `SignalType`.
var signal: Signal<Value, Error> { get }
}
@ -160,12 +160,12 @@ internal protocol InternalSignalType: SignalType {
public extension SignalType {
/// Adds an observer to the Signal which observes any future events from the Signal.
/// If the Signal has already terminated, the observer will immediately receive an
/// Adds an observer to the `Signal` which observes any future events from the `Signal`.
/// If the `Signal` has already terminated, the observer will immediately receive an
/// `Interrupted` event.
///
/// Returns a Disposable which can be used to disconnect the observer. Disposing
/// of the Disposable will have no effect on the Signal itself.
/// of the Disposable will have no effect on the `Signal` itself.
@discardableResult
public func add(observer: Observer<Value, Error>) -> Disposable? {
let token = signal.observers.insert(value: observer)

View File

@ -8,14 +8,14 @@
import Foundation
public final class ColdSignal<V, E: Swift.Error>: ColdSignalType, InternalSignalType, SpecialSignalGenerator {
public final class Source<V, E: Swift.Error>: SourceType, InternalSignalType, SpecialSignalGenerator {
public typealias Value = V
public typealias Error = E
internal var observers = Bag<Observer<Value, Error>>()
public var coldSignal: ColdSignal {
public var source: Source {
return self
}
@ -25,11 +25,11 @@ public final class ColdSignal<V, E: Swift.Error>: ColdSignalType, InternalSignal
private var started = false
/// Initializes a ColdSignal that will invoke the given closure at the
/// Initializes a Source that will invoke the given closure at the
/// invocation of `start()`.
///
/// The events that the closure puts into the given observer will become
/// the events sent to this ColdSignal.
/// the events sent to this `Source`.
///
/// In order to stop or dispose of the signal, invoke `stop()`. Calling this method
/// will dispose of the disposable returned by the given closure.
@ -69,83 +69,83 @@ public final class ColdSignal<V, E: Swift.Error>: ColdSignalType, InternalSignal
}
extension ColdSignal: CustomDebugStringConvertible {
extension Source: CustomDebugStringConvertible {
public var debugDescription: String {
let obs = Array(self.observers.map { String(describing: $0) })
return "ColdSignal[\(obs.joined(separator: ", "))]"
return "Source[\(obs.joined(separator: ", "))]"
}
}
public protocol ColdSignalType: SignalType {
public protocol SourceType: SignalType {
/// The exposed raw signal that underlies the ColdSignalType
var coldSignal: ColdSignal<Value, Error> { get }
/// The exposed raw signal that underlies the SourceType
var source: Source<Value, Error> { get }
/// Invokes the closure provided upon initialization, and passes in a newly
/// created observer to which events can be sent.
func start()
/// Stops the ColdSignal by sending an interrupt to all of it's
/// Stops the `Source` by sending an interrupt to all of it's
/// observers and then invoking the disposable returned by the closure
/// that was provided upon initialization.
func stop()
}
public extension ColdSignalType {
public extension SourceType {
public var signal: Signal<Value, Error> {
return Signal { observer in
self.coldSignal.add(observer: observer)
self.source.add(observer: observer)
}
}
/// Invokes the closure provided upon initialization, and passes in a newly
/// created observer to which events can be sent.
func start() {
coldSignal.start()
source.start()
}
/// Stops the ColdSignal by sending an interrupt to all of it's
/// Stops the `Source` by sending an interrupt to all of it's
/// observers and then invoking the disposable returned by the closure
/// that was provided upon initialization.
func stop() {
coldSignal.stop()
source.stop()
}
}
public extension ColdSignalType {
public extension SourceType {
/// Adds an observer to the ColdSignal which observes any future events from the
/// ColdSignal. If the Signal has already terminated, the observer will immediately
/// Adds an observer to the `Source` which observes any future events from the
/// `Source`. If the `Signal` has already terminated, the observer will immediately
/// receive an `Interrupted` event.
///
/// Returns a Disposable which can be used to disconnect the observer. Disposing
/// of the Disposable will have no effect on the Signal itself.
@discardableResult
public func add(observer: Observer<Value, Error>) -> Disposable? {
let token = coldSignal.observers.insert(value: observer)
return ActionDisposable {
self.coldSignal.observers.removeValueForToken(token: token)
let token = source.observers.insert(value: observer)
return ActionDisposable { [weak source = source] in
source?.observers.removeValueForToken(token: token)
}
}
/// Creates a ColdSignal, adds exactly one observer, and then immediately
/// invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer, and then immediately
/// invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
public func start(with observer: Observer<Value, Error>) -> Disposable? {
let disposable = coldSignal.add(observer: observer)
self.coldSignal.start()
let disposable = source.add(observer: observer)
source.start()
return disposable
}
/// Creates a ColdSignal, adds exactly one observer, and then immediately
/// invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer, and then immediately
/// invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
@ -153,8 +153,8 @@ public extension ColdSignalType {
return start(with: Observer(observerAction))
}
/// Creates a ColdSignal, adds exactly one observer for next, and then immediately
/// invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer for next, and then immediately
/// invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
@ -162,8 +162,8 @@ public extension ColdSignalType {
return start(with: Observer(next: next))
}
/// Creates a ColdSignal, adds exactly one observer for completed events, and then
/// immediately invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer for completed events, and then
/// immediately invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
@ -171,8 +171,8 @@ public extension ColdSignalType {
return start(with: Observer(completed: completed))
}
/// Creates a ColdSignal, adds exactly one observer for errors, and then
/// immediately invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer for errors, and then
/// immediately invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
@ -180,8 +180,8 @@ public extension ColdSignalType {
return start(with: Observer(failed: failed))
}
/// Creates a ColdSignal, adds exactly one observer for interrupts, and then
/// immediately invokes start on the ColdSignal.
/// Creates a `Source`, adds exactly one observer for interrupts, and then
/// immediately invokes start on the `Source`.
///
/// Returns a Disposable which can be used to dispose of the added observer.
@discardableResult
@ -191,65 +191,65 @@ public extension ColdSignalType {
}
public extension ColdSignalType {
public extension SourceType {
/// Creates a new `ColdSignal` which will apply a unary operator directly to events
/// Creates a new `Source` which will apply a unary operator directly to events
/// produced by the `startHandler`.
///
/// The new `ColdSignal` is in no way related to the source `ColdSignal` except
/// The new `Source` is in no way related to the source `Source` except
/// that they share a reference to the same `startHandler`.
public func lift<U, F>(_ transform: @escaping (Signal<Value, Error>) -> Signal<U, F>) -> ColdSignal<U, F> {
return ColdSignal { observer in
public func lift<U, F>(_ transform: @escaping (Signal<Value, Error>) -> Signal<U, F>) -> Source<U, F> {
return Source { observer in
let (pipeSignal, pipeObserver) = Signal<Value, Error>.pipe()
transform(pipeSignal).add(observer: observer)
return self.coldSignal.startHandler(pipeObserver)
return self.source.startHandler(pipeObserver)
}
}
public func lift<U, F>(_ transform: @escaping (Signal<Value, Error>) -> (Signal<U, F>, Signal<U, F>))
-> (ColdSignal<U, F>, ColdSignal<U, F>)
-> (Source<U, F>, Source<U, F>)
{
let (pipeSignal, pipeObserver) = Signal<Value, Error>.pipe()
let (left, right) = transform(pipeSignal)
let coldLeft = ColdSignal<U, F> { observer in
let sourceLeft = Source<U, F> { observer in
left.add(observer: observer)
return self.coldSignal.startHandler(pipeObserver)
return self.source.startHandler(pipeObserver)
}
let coldRight = ColdSignal<U, F> { observer in
let sourceRight = Source<U, F> { observer in
right.add(observer: observer)
return self.coldSignal.startHandler(pipeObserver)
return self.source.startHandler(pipeObserver)
}
return (coldLeft, coldRight)
return (sourceLeft, sourceRight)
}
/// Maps each value in the signal to a new value.
public func map<U>(_ transform: @escaping (Value) -> U) -> ColdSignal<U, Error> {
public func map<U>(_ transform: @escaping (Value) -> U) -> Source<U, Error> {
return lift { $0.map(transform) }
}
/// Maps errors in the signal to a new error.
public func mapError<F>(_ transform: @escaping (Error) -> F) -> ColdSignal<Value, F> {
public func mapError<F>(_ transform: @escaping (Error) -> F) -> Source<Value, F> {
return lift { $0.mapError(transform) }
}
/// Preserves only the values of the signal that pass the given predicate.
public func filter(_ predicate: @escaping (Value) -> Bool) -> ColdSignal<Value, Error> {
public func filter(_ predicate: @escaping (Value) -> Bool) -> Source<Value, Error> {
return lift { $0.filter(predicate) }
}
/// Splits the signal into two signals. The first signal in the tuple matches the
/// predicate, the second signal does not match the predicate
public func partition(_ predicate: @escaping (Value) -> Bool)
-> (ColdSignal<Value, Error>, ColdSignal<Value, Error>) {
-> (Source<Value, Error>, Source<Value, Error>) {
return lift { $0.partition(predicate) }
}
/// Aggregate values into a single combined value. Mirrors the Swift Collection
public func reduce<T>(initial: T, _ combine: @escaping (T, Value) -> T) -> ColdSignal<T, Error> {
public func reduce<T>(initial: T, _ combine: @escaping (T, Value) -> T) -> Source<T, Error> {
return lift { $0.reduce(initial: initial, combine) }
}
public func flatMap<U>(_ transform: @escaping (Value) -> U?) -> ColdSignal<U, Error> {
public func flatMap<U>(_ transform: @escaping (Value) -> U?) -> Source<U, Error> {
return lift { $0.flatMap(transform) }
}