Skip to content

Commit ac1a13e

Browse files
committed
Pretty significant refactor and improved memory/resource management.
1 parent 46a7262 commit ac1a13e

File tree

4 files changed

+181
-157
lines changed

4 files changed

+181
-157
lines changed

Sources/ColdSignal.swift

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,21 @@
88

99
import Foundation
1010

11-
public final class ColdSignal<T, E: Error>: ColdSignalType, InternalSignalType, SpecialSignalGenerator {
11+
public final class ColdSignal<V, E: Swift.Error>: ColdSignalType, InternalSignalType, SpecialSignalGenerator {
1212

13-
public typealias Value = T
14-
public typealias ErrorType = E
13+
public typealias Value = V
14+
public typealias Error = E
1515

16-
internal var observers = Bag<Observer<Value, ErrorType>>()
16+
internal var observers = Bag<Observer<Value, Error>>()
1717

1818
public var coldSignal: ColdSignal {
1919
return self
2020
}
2121

22-
internal let startHandler: (Observer<Value, ErrorType>) -> Disposable?
22+
internal let startHandler: (Observer<Value, Error>) -> Disposable?
2323

2424
private var cancelDisposable: Disposable?
2525

26-
private var handlerDisposable: Disposable?
27-
2826
private var started = false
2927

3028
/// Initializes a ColdSignal that will invoke the given closure at the
@@ -38,7 +36,7 @@ public final class ColdSignal<T, E: Error>: ColdSignalType, InternalSignalType,
3836
///
3937
/// Invoking `start()` will have no effect until the signal is stopped. After
4038
/// `stop()` is called this process may be repeated.
41-
public init(_ generator: @escaping (Observer<Value, ErrorType>) -> Disposable?) {
39+
public init(_ generator: @escaping (Observer<Value, Error>) -> Disposable?) {
4240
self.startHandler = generator
4341
}
4442

@@ -47,31 +45,19 @@ public final class ColdSignal<T, E: Error>: ColdSignalType, InternalSignalType,
4745
///
4846
/// Returns a Disposable which can be used to interrupt the work associated
4947
/// with the signal and immediately send an `Interrupted` event.
50-
5148
@discardableResult
5249
public func start() {
5350
if !started {
5451
started = true
5552

56-
let observer = Observer<Value, ErrorType> { event in
57-
// Pass event downstream
58-
self.observers.forEach { (observer) in
59-
observer.action(event)
60-
}
61-
62-
// If event is terminating dispose of the handlerDisposable.
63-
if event.isTerminating {
64-
self.handlerDisposable?.dispose()
65-
}
66-
}
67-
68-
handlerDisposable = startHandler(observer)
53+
let observer = Observer(with: CircuitBreaker(holding: self))
54+
let handlerDisposable = startHandler(observer)
6955

7056
// The cancel disposable should send interrupted and then dispose of the
7157
// disposable produced by the startHandler.
72-
cancelDisposable = ActionDisposable { [weak self] in
58+
cancelDisposable = ActionDisposable {
7359
observer.sendInterrupted()
74-
self?.handlerDisposable?.dispose()
60+
handlerDisposable?.dispose()
7561
}
7662
}
7763
}
@@ -95,7 +81,7 @@ extension ColdSignal: CustomDebugStringConvertible {
9581
public protocol ColdSignalType: SignalType {
9682

9783
/// The exposed raw signal that underlies the ColdSignalType
98-
var coldSignal: ColdSignal<Value, ErrorType> { get }
84+
var coldSignal: ColdSignal<Value, Error> { get }
9985

10086
/// Invokes the closure provided upon initialization, and passes in a newly
10187
/// created observer to which events can be sent.
@@ -110,7 +96,7 @@ public protocol ColdSignalType: SignalType {
11096

11197
public extension ColdSignalType {
11298

113-
public var signal: Signal<Value, ErrorType> {
99+
public var signal: Signal<Value, Error> {
114100
return Signal { observer in
115101
self.coldSignal.add(observer: observer)
116102
}
@@ -140,7 +126,7 @@ public extension ColdSignalType {
140126
/// Returns a Disposable which can be used to disconnect the observer. Disposing
141127
/// of the Disposable will have no effect on the Signal itself.
142128
@discardableResult
143-
public func add(observer: Observer<Value, ErrorType>) -> Disposable? {
129+
public func add(observer: Observer<Value, Error>) -> Disposable? {
144130
let token = coldSignal.observers.insert(value: observer)
145131
return ActionDisposable {
146132
self.coldSignal.observers.removeValueForToken(token: token)
@@ -152,7 +138,7 @@ public extension ColdSignalType {
152138
///
153139
/// Returns a Disposable which can be used to dispose of the added observer.
154140
@discardableResult
155-
public func start(with observer: Observer<Value, ErrorType>) -> Disposable? {
141+
public func start(with observer: Observer<Value, Error>) -> Disposable? {
156142
let disposable = coldSignal.add(observer: observer)
157143
self.coldSignal.start()
158144
return disposable
@@ -163,7 +149,7 @@ public extension ColdSignalType {
163149
///
164150
/// Returns a Disposable which can be used to dispose of the added observer.
165151
@discardableResult
166-
public func start(_ observerAction: @escaping Observer<Value, ErrorType>.Action) -> Disposable? {
152+
public func start(_ observerAction: @escaping Observer<Value, Error>.Action) -> Disposable? {
167153
return start(with: Observer(observerAction))
168154
}
169155

@@ -190,7 +176,7 @@ public extension ColdSignalType {
190176
///
191177
/// Returns a Disposable which can be used to dispose of the added observer.
192178
@discardableResult
193-
public func startWithFailed(failed: @escaping (ErrorType) -> Void) -> Disposable? {
179+
public func startWithFailed(failed: @escaping (Error) -> Void) -> Disposable? {
194180
return start(with: Observer(failed: failed))
195181
}
196182

@@ -212,18 +198,18 @@ public extension ColdSignalType {
212198
///
213199
/// The new `ColdSignal` is in no way related to the source `ColdSignal` except
214200
/// that they share a reference to the same `startHandler`.
215-
public func lift<U, F>(_ transform: @escaping (Signal<Value, ErrorType>) -> Signal<U, F>) -> ColdSignal<U, F> {
201+
public func lift<U, F>(_ transform: @escaping (Signal<Value, Error>) -> Signal<U, F>) -> ColdSignal<U, F> {
216202
return ColdSignal { observer in
217-
let (pipeSignal, pipeObserver) = Signal<Value, ErrorType>.pipe()
203+
let (pipeSignal, pipeObserver) = Signal<Value, Error>.pipe()
218204
transform(pipeSignal).add(observer: observer)
219205
return self.coldSignal.startHandler(pipeObserver)
220206
}
221207
}
222208

223-
public func lift<U, F>(_ transform: @escaping (Signal<Value, ErrorType>) -> (Signal<U, F>, Signal<U, F>))
209+
public func lift<U, F>(_ transform: @escaping (Signal<Value, Error>) -> (Signal<U, F>, Signal<U, F>))
224210
-> (ColdSignal<U, F>, ColdSignal<U, F>)
225211
{
226-
let (pipeSignal, pipeObserver) = Signal<Value, ErrorType>.pipe()
212+
let (pipeSignal, pipeObserver) = Signal<Value, Error>.pipe()
227213
let (left, right) = transform(pipeSignal)
228214
let coldLeft = ColdSignal<U, F> { observer in
229215
left.add(observer: observer)
@@ -237,33 +223,33 @@ public extension ColdSignalType {
237223
}
238224

239225
/// Maps each value in the signal to a new value.
240-
public func map<U>(_ transform: @escaping (Value) -> U) -> ColdSignal<U, ErrorType> {
226+
public func map<U>(_ transform: @escaping (Value) -> U) -> ColdSignal<U, Error> {
241227
return lift { $0.map(transform) }
242228
}
243229

244230
/// Maps errors in the signal to a new error.
245-
public func mapError<F>(_ transform: @escaping (ErrorType) -> F) -> ColdSignal<Value, F> {
231+
public func mapError<F>(_ transform: @escaping (Error) -> F) -> ColdSignal<Value, F> {
246232
return lift { $0.mapError(transform) }
247233
}
248234

249235
/// Preserves only the values of the signal that pass the given predicate.
250-
public func filter(_ predicate: @escaping (Value) -> Bool) -> ColdSignal<Value, ErrorType> {
236+
public func filter(_ predicate: @escaping (Value) -> Bool) -> ColdSignal<Value, Error> {
251237
return lift { $0.filter(predicate) }
252238
}
253239

254240
/// Splits the signal into two signals. The first signal in the tuple matches the
255241
/// predicate, the second signal does not match the predicate
256242
public func partition(_ predicate: @escaping (Value) -> Bool)
257-
-> (ColdSignal<Value, ErrorType>, ColdSignal<Value, ErrorType>) {
243+
-> (ColdSignal<Value, Error>, ColdSignal<Value, Error>) {
258244
return lift { $0.partition(predicate) }
259245
}
260246

261247
/// Aggregate values into a single combined value. Mirrors the Swift Collection
262-
public func reduce<T>(initial: T, _ combine: @escaping (T, Value) -> T) -> ColdSignal<T, ErrorType> {
248+
public func reduce<T>(initial: T, _ combine: @escaping (T, Value) -> T) -> ColdSignal<T, Error> {
263249
return lift { $0.reduce(initial: initial, combine) }
264250
}
265251

266-
public func flatMap<U>(_ transform: @escaping (Value) -> U?) -> ColdSignal<U, ErrorType> {
252+
public func flatMap<U>(_ transform: @escaping (Value) -> U?) -> ColdSignal<U, Error> {
267253
return lift { $0.flatMap(transform) }
268254
}
269255

Sources/Event.swift

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,93 +11,93 @@ import Foundation
1111
/// Represents a signal event.
1212
///
1313
/// Signals must conform to the grammar:
14-
/// `Next* (Failed | Completed | Interrupted)?`
15-
public enum Event<Value, ErrorType: Error> {
14+
/// `next* (failed | completed | interrupted)?`
15+
public enum Event<Value, Error: Swift.Error> {
1616

1717
/// A value provided by the signal.
18-
case Next(Value)
18+
case next(Value)
1919

2020
/// The signal terminated because of an error. No further events will be
2121
/// received.
22-
case Failed(ErrorType)
22+
case failed(Error)
2323

2424
/// The signal successfully terminated. No further events will be received.
25-
case Completed
25+
case completed
2626

2727
/// Event production on the signal has been interrupted. No further events
2828
/// will be received.
29-
case Interrupted
29+
case interrupted
3030

3131

3232
/// Whether this event indicates signal termination (i.e., that no further
3333
/// events will be received).
3434
public var isTerminating: Bool {
3535
switch self {
36-
case .Next:
36+
case .next:
3737
return false
3838

39-
case .Failed, .Completed, .Interrupted:
39+
case .failed, .completed, .interrupted:
4040
return true
4141
}
4242
}
4343

4444
/// Lifts the given function over the event's value.
45-
public func map<U>(_ f: (Value) -> U) -> Event<U, ErrorType> {
45+
public func map<U>(_ f: (Value) -> U) -> Event<U, Error> {
4646
switch self {
47-
case let .Next(value):
48-
return .Next(f(value))
47+
case let .next(value):
48+
return .next(f(value))
4949

50-
case let .Failed(error):
51-
return .Failed(error)
50+
case let .failed(error):
51+
return .failed(error)
5252

53-
case .Completed:
54-
return .Completed
53+
case .completed:
54+
return .completed
5555

56-
case .Interrupted:
57-
return .Interrupted
56+
case .interrupted:
57+
return .interrupted
5858
}
5959
}
6060

6161
/// Lifts the given function over the event's value.
62-
public func flatMap<U>(_ f: (Value) -> U?) -> Event<U, ErrorType>? {
62+
public func flatMap<U>(_ f: (Value) -> U?) -> Event<U, Error>? {
6363
switch self {
64-
case let .Next(value):
64+
case let .next(value):
6565
if let nextValue = f(value) {
66-
return .Next(nextValue)
66+
return .next(nextValue)
6767
}
6868
return nil
6969

70-
case let .Failed(error):
71-
return .Failed(error)
70+
case let .failed(error):
71+
return .failed(error)
7272

73-
case .Completed:
74-
return .Completed
73+
case .completed:
74+
return .completed
7575

76-
case .Interrupted:
77-
return .Interrupted
76+
case .interrupted:
77+
return .interrupted
7878
}
7979
}
8080

8181
/// Lifts the given function over the event's error.
82-
public func mapError<F>(_ f: (ErrorType) -> F) -> Event<Value, F> {
82+
public func mapError<F>(_ f: (Error) -> F) -> Event<Value, F> {
8383
switch self {
84-
case let .Next(value):
85-
return .Next(value)
84+
case let .next(value):
85+
return .next(value)
8686

87-
case let .Failed(error):
88-
return .Failed(f(error))
87+
case let .failed(error):
88+
return .failed(f(error))
8989

90-
case .Completed:
91-
return .Completed
90+
case .completed:
91+
return .completed
9292

93-
case .Interrupted:
94-
return .Interrupted
93+
case .interrupted:
94+
return .interrupted
9595
}
9696
}
9797

9898
/// Unwraps the contained `Next` value.
9999
public var value: Value? {
100-
if case let .Next(value) = self {
100+
if case let .next(value) = self {
101101
return value
102102
} else {
103103
return nil
@@ -106,26 +106,26 @@ public enum Event<Value, ErrorType: Error> {
106106

107107
/// Unwraps the contained `Error` value.
108108
public var error: Error? {
109-
if case let .Failed(error) = self {
109+
if case let .failed(error) = self {
110110
return error
111111
} else {
112112
return nil
113113
}
114114
}
115115
}
116116

117-
public func == <Value: Equatable, ErrorType: Equatable> (lhs: Event<Value, ErrorType>, rhs: Event<Value, ErrorType>) -> Bool {
117+
public func == <Value: Equatable, Error: Equatable> (lhs: Event<Value, Error>, rhs: Event<Value, Error>) -> Bool {
118118
switch (lhs, rhs) {
119-
case let (.Next(left), .Next(right)):
119+
case let (.next(left), .next(right)):
120120
return left == right
121121

122-
case let (.Failed(left), .Failed(right)):
122+
case let (.failed(left), .failed(right)):
123123
return left == right
124124

125-
case (.Completed, .Completed):
125+
case (.completed, .completed):
126126
return true
127127

128-
case (.Interrupted, .Interrupted):
128+
case (.interrupted, .interrupted):
129129
return true
130130

131131
default:

0 commit comments

Comments
 (0)