Skip to content

Commit b14a530

Browse files
committed
Fix apple#174
1 parent 1b18131 commit b14a530

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

Sources/AsyncAlgorithms/Debounce/DebounceStateMachine.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,15 @@ struct DebounceStateMachine<Base: AsyncSequence, C: Clock> {
325325
upstreamContinuation: UnsafeContinuation<Void, Error>?,
326326
clockContinuation: UnsafeContinuation<C.Instant, Error>?
327327
)
328+
/// Indicates that the downstream continuation should be resumed with `nil` and
329+
/// the task and the upstream continuation should be cancelled.
330+
case resumeContinuationWithElementAndCancelTaskAndUpstreamAndClockContinuation(
331+
downstreamContinuation: UnsafeContinuation<Element?, Error>,
332+
element: Element,
333+
task: Task<Void, Never>,
334+
upstreamContinuation: UnsafeContinuation<Void, Error>?,
335+
clockContinuation: UnsafeContinuation<C.Instant, Error>?
336+
)
328337
/// Indicates that nothing should be done.
329338
case none
330339
}
@@ -372,13 +381,14 @@ struct DebounceStateMachine<Base: AsyncSequence, C: Clock> {
372381
clockContinuation: clockContinuation
373382
)
374383

375-
case .debouncing(let task, let upstreamContinuation, let downstreamContinuation, _):
384+
case .debouncing(let task, let upstreamContinuation, let downstreamContinuation, let currentElement):
376385
// We are debouncing and the upstream finished. At this point
377-
// we can just resume the downstream continuation with nil and cancel everything else
386+
// we can just resume the downstream continuation with element and cancel everything else
378387
self.state = .finished
379388

380-
return .resumeContinuationWithNilAndCancelTaskAndUpstreamAndClockContinuation(
389+
return .resumeContinuationWithElementAndCancelTaskAndUpstreamAndClockContinuation(
381390
downstreamContinuation: downstreamContinuation,
391+
element: currentElement.element,
382392
task: task,
383393
upstreamContinuation: upstreamContinuation,
384394
clockContinuation: nil

Sources/AsyncAlgorithms/Debounce/DebounceStorage.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,23 @@ final class DebounceStorage<Base: AsyncSequence, C: Clock>: @unchecked Sendable
119119
downstreamContinuation.resume(returning: nil)
120120

121121
break loop
122+
123+
case .resumeContinuationWithElementAndCancelTaskAndUpstreamAndClockContinuation(
124+
let downstreamContinuation,
125+
let element,
126+
let task,
127+
let upstreamContinuation,
128+
let clockContinuation
129+
):
130+
upstreamContinuation?.resume(throwing: CancellationError())
131+
clockContinuation?.resume(throwing: CancellationError())
132+
task.cancel()
133+
134+
downstreamContinuation.resume(returning: element)
135+
136+
break loop
137+
138+
122139
case .none:
123140

124141
break loop

Sources/AsyncAlgorithms/Locking.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,27 @@ internal struct Lock {
8787
func unlock() {
8888
Lock.unlock(platformLock)
8989
}
90+
91+
/// Acquire the lock for the duration of the given block.
92+
///
93+
/// This convenience method should be preferred to `lock` and `unlock` in
94+
/// most situations, as it ensures that the lock will be released regardless
95+
/// of how `body` exits.
96+
///
97+
/// - Parameter body: The block to execute while holding the lock.
98+
/// - Returns: The value returned by the block.
99+
func withLock<T>(_ body: () throws -> T) rethrows -> T {
100+
self.lock()
101+
defer {
102+
self.unlock()
103+
}
104+
return try body()
105+
}
106+
107+
// specialise Void return (for performance)
108+
func withLockVoid(_ body: () throws -> Void) rethrows -> Void {
109+
try self.withLock(body)
110+
}
90111
}
91112

92113
struct ManagedCriticalState<State> {

Tests/AsyncAlgorithmsTests/TestDebounce.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ final class TestDebounce: XCTestCase {
2727
validate {
2828
"abcd----e---f-g-|"
2929
$0.inputs[0].debounce(for: .steps(3), clock: $0.clock)
30-
"------d----e----|"
30+
"------d----e----[g|]"
3131
}
3232
}
3333

@@ -37,7 +37,7 @@ final class TestDebounce: XCTestCase {
3737
validate {
3838
"a|"
3939
$0.inputs[0].debounce(for: .steps(3), clock: $0.clock)
40-
"-|"
40+
"-[a|]"
4141
}
4242
}
4343

0 commit comments

Comments
 (0)