Skip to content

Commit a4317c6

Browse files
committed
Back Signal.Core.state with Atomic.
1 parent d6268d3 commit a4317c6

File tree

1 file changed

+10
-29
lines changed

1 file changed

+10
-29
lines changed

Sources/Signal.swift

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ public final class Signal<Value, Error: Swift.Error> {
100100
/// Nevertheless, this should not cause the termination event being
101101
/// sent multiple times, since `tryTerminate` would not respond to false
102102
/// positives.
103-
private var state: State
103+
private var state: State {
104+
get { return _state.value }
105+
set { _state.value = newValue }
106+
}
107+
108+
private let _state: Atomic<State>
104109

105110
/// Used to ensure that state updates are serialized.
106111
private let updateLock: Lock
@@ -112,7 +117,7 @@ public final class Signal<Value, Error: Swift.Error> {
112117
private var hasDeinitialized: Bool
113118

114119
fileprivate init(_ generator: (Observer) -> Disposable?) {
115-
state = .alive(AliveState(observers: Bag()))
120+
_state = Atomic(.alive(AliveState(observers: Bag())))
116121

117122
updateLock = Lock.make()
118123
sendLock = Lock.make()
@@ -163,43 +168,19 @@ public final class Signal<Value, Error: Swift.Error> {
163168
} else {
164169
var result = OperationResult.none
165170

166-
// The `terminating` status check is performed twice for two different
167-
// purposes:
168-
//
169-
// 1. Within the main protected section
170-
// It guarantees that a recursive termination event sent by a
171-
// downstream consumer, is immediately processed and need not compete
172-
// with concurrent pending senders (if any).
173-
//
174-
// Termination events sent concurrently may also be caught here, but
175-
// not necessarily all of them due to data races.
176-
//
177-
// 2. After the main protected section
178-
// It ensures the termination event sent concurrently that are not
179-
// caught by (1) due to data races would still be processed.
180-
//
181-
// The related PR on the race conditions:
182-
// https://github.com/ReactiveCocoa/ReactiveSwift/pull/112
183-
184171
self.sendLock.lock()
185172

186173
if case let .alive(state) = self.state {
187174
for observer in state.observers {
188175
observer.action(event)
189176
}
190-
191-
// Check if the status has been bumped to `terminating` due to a
192-
// concurrent or a recursive termination event.
193-
if case .terminating = self.state {
194-
result = self.tryToCommitTermination(acquired: self.sendLock)
195-
}
196177
}
197178

198179
self.sendLock.unlock()
199180

200-
// Check if the status has been bumped to `terminating` due to a
201-
// concurrent termination event that has not been caught in the main
202-
// protected section.
181+
// Check if any observer or any concurrent sender has been bumped to
182+
// `terminating` due to a concurrent termination event that has not been
183+
// caught in the main protected section.
203184
if result == .none, case .terminating = self.state {
204185
result = self.tryToCommitTermination()
205186
}

0 commit comments

Comments
 (0)