Skip to content

Commit

Permalink
Fix DemandBuffer race (#3475)
Browse files Browse the repository at this point in the history
See also: CombineCommunity/CombineExt#90

Co-authored-by: Stephen Celis <[email protected]>
  • Loading branch information
kabiroberai and stephencelis authored Nov 12, 2024
1 parent 12268ed commit 8784f76
Showing 1 changed file with 8 additions and 9 deletions.
17 changes: 8 additions & 9 deletions Sources/ComposableArchitecture/Internal/Create.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,23 @@
// THE SOFTWARE.

@preconcurrency import Combine
import Darwin
import Foundation

final class DemandBuffer<S: Subscriber>: @unchecked Sendable {
private var buffer = [S.Input]()
private let subscriber: S
private var completion: Subscribers.Completion<S.Failure>?
private var demandState = Demand()
private let lock: os_unfair_lock_t
private let lock = NSRecursiveLock()

init(subscriber: S) {
self.subscriber = subscriber
self.lock = os_unfair_lock_t.allocate(capacity: 1)
self.lock.initialize(to: os_unfair_lock())
}

deinit {
self.lock.deinitialize(count: 1)
self.lock.deallocate()
}

func buffer(value: S.Input) -> Subscribers.Demand {
lock.lock()
defer { lock.unlock() }

precondition(
self.completion == nil, "How could a completed publisher sent values?! Beats me 🤷‍♂️")

Expand All @@ -55,6 +51,9 @@ final class DemandBuffer<S: Subscriber>: @unchecked Sendable {
}

func complete(completion: Subscribers.Completion<S.Failure>) {
lock.lock()
defer { lock.unlock() }

precondition(
self.completion == nil, "Completion have already occurred, which is quite awkward 🥺")

Expand Down

0 comments on commit 8784f76

Please sign in to comment.