Skip to content

Commit 56131fc

Browse files
committed
Fixed the use of disposables in EventGeneratingCore. Relaxed UnsafeAtomicState.is.
1 parent ce3fe65 commit 56131fc

File tree

3 files changed

+41
-19
lines changed

3 files changed

+41
-19
lines changed

Sources/Atomic.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ internal struct UnsafeAtomicState<State: RawRepresentable> where State.RawValue
4242
/// - returns: `true` if the current state matches the expected state.
4343
/// `false` otherwise.
4444
internal func `is`(_ expected: State) -> Bool {
45-
return OSAtomicCompareAndSwap32Barrier(expected.rawValue,
46-
expected.rawValue,
47-
value)
45+
return expected.rawValue == value.pointee
4846
}
4947

5048
/// Try to transition from the expected current state to the specified next
@@ -82,7 +80,7 @@ internal struct UnsafeAtomicState<State: RawRepresentable> where State.RawValue
8280
/// - returns: `true` if the current state matches the expected state.
8381
/// `false` otherwise.
8482
internal func `is`(_ expected: State) -> Bool {
85-
return value.modify { $0 == expected.rawValue }
83+
return value.value == expected.rawValue
8684
}
8785

8886
/// Try to transition from the expected current state to the specified next

Sources/Disposable.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,27 @@ extension UnsafeAtomicState where State == DisposableState {
3838
}
3939
}
4040

41+
/// A disposable that has already been disposed.
42+
internal final class _SimpleDisposable: Disposable {
43+
private let state = UnsafeAtomicState<DisposableState>(.active)
44+
45+
var isDisposed: Bool {
46+
return state.is(.disposed)
47+
}
48+
49+
func dispose() {
50+
_ = state.tryDispose()
51+
}
52+
53+
deinit {
54+
state.deinitialize()
55+
}
56+
}
57+
58+
/// A disposable that has already been disposed.
4159
internal final class NopDisposable: Disposable {
4260
static let shared = NopDisposable()
43-
var isDisposed = false
61+
var isDisposed = true
4462
func dispose() {}
4563
private init() {}
4664
}

Sources/SignalProducer.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public struct SignalProducer<Value, Error: Swift.Error> {
6363
/// - parameters:
6464
/// - startHandler: A closure that accepts observer and a disposable.
6565
public init(_ startHandler: @escaping (Signal<Value, Error>.Observer, Lifetime) -> Void) {
66-
core = SignalCore {
66+
self.init(SignalCore {
6767
let disposable = CompositeDisposable()
6868
let (signal, observer) = Signal<Value, Error>.pipe(disposable: disposable)
6969
let observerDidSetup = { startHandler(observer, Lifetime(disposable)) }
@@ -72,7 +72,7 @@ public struct SignalProducer<Value, Error: Swift.Error> {
7272
return SignalProducerCore.ProducedSignalReceipt(signal: signal,
7373
observerDidSetup: observerDidSetup,
7474
interruptHandle: interruptHandle)
75-
}
75+
})
7676
}
7777

7878
/// Create a SignalProducer.
@@ -168,14 +168,16 @@ public struct SignalProducer<Value, Error: Swift.Error> {
168168
/// - values: A sequence of values that a `Signal` will send as separate
169169
/// `value` events and then complete.
170170
public init<S: Sequence>(_ values: S) where S.Iterator.Element == Value {
171-
self.init(EventGeneratingCore { observer, disposable in
172-
for value in values where !disposable.isDisposed {
171+
self.init(EventGeneratingCore(isDisposable: true) { observer, disposable in
172+
for value in values {
173173
observer.send(value: value)
174-
}
175174

176-
if !disposable.isDisposed {
177-
observer.sendCompleted()
175+
if disposable.isDisposed {
176+
break
177+
}
178178
}
179+
180+
observer.sendCompleted()
179181
})
180182
}
181183

@@ -335,14 +337,18 @@ private final class EventTransformingCore<Value, Error: Swift.Error, SourceValue
335337
/// It is intended for constant `SignalProducers`s that synchronously emits all events
336338
/// without escaping the `Observer`.
337339
private final class EventGeneratingCore<Value, Error: Swift.Error>: SignalProducerCore<Value, Error> {
340+
private let isDisposable: Bool
338341
private let generator: (Signal<Value, Error>.Observer, Disposable) -> Void
339342

340-
init(_ generator: @escaping (Signal<Value, Error>.Observer, Disposable) -> Void) {
343+
init(isDisposable: Bool = false, _ generator: @escaping (Signal<Value, Error>.Observer, Disposable) -> Void) {
344+
self.isDisposable = isDisposable
341345
self.generator = generator
342346
}
343347

344348
internal override func start(_ observer: Signal<Value, Error>.Observer) -> Disposable {
345-
let d = NopDisposable.shared
349+
// Object allocation is a considerable overhead. So unless the core is configured
350+
// to be disposable, we would reuse the already-disposed, shared `NopDisposable`.
351+
let d: Disposable = isDisposable ? _SimpleDisposable() : NopDisposable.shared
346352
generator(observer, d)
347353
return d
348354
}
@@ -365,10 +371,10 @@ extension SignalProducer where Error == NoError {
365371
/// - value: A value that should be sent by the `Signal` in a `value`
366372
/// event.
367373
public init(value: Value) {
368-
self.init { observer, _ in
374+
self.init(EventGeneratingCore { observer, _ in
369375
observer.send(value: value)
370376
observer.sendCompleted()
371-
}
377+
})
372378
}
373379

374380
/// Creates a producer for a Signal that will immediately send the values
@@ -378,17 +384,17 @@ extension SignalProducer where Error == NoError {
378384
/// - values: A sequence of values that a `Signal` will send as separate
379385
/// `value` events and then complete.
380386
public init<S: Sequence>(_ values: S) where S.Iterator.Element == Value {
381-
self.init { observer, lifetime in
387+
self.init(EventGeneratingCore(isDisposable: true) { observer, disposable in
382388
for value in values {
383389
observer.send(value: value)
384390

385-
if lifetime.hasEnded {
391+
if disposable.isDisposed {
386392
break
387393
}
388394
}
389395

390396
observer.sendCompleted()
391-
}
397+
})
392398
}
393399

394400
/// Creates a producer for a Signal that will immediately send the values

0 commit comments

Comments
 (0)