11import Foundation
22
3- /// Unified serial async task queue with operation-type-aware coalescing .
4- /// - Non-coalescable operations always execute in order
5- /// - Consecutive coalescable operations are coalesced ( only the last one executes)
3+ /// Unified serial async task queue with operation-type-aware last-wins semantics .
4+ /// - Non-last-wins operations always execute in order
5+ /// - Consecutive last-wins operations: only the last one executes
66/// - Order is always preserved
77internal actor AsyncUnifiedQueue {
88 private var currentTask : Task < Void , Never > ?
99
1010 private struct QueuedOperation {
1111 let operation : ( ) async -> Void
1212 let continuation : CheckedContinuation < Void , Never >
13- let canCoalesce : Bool
13+ let lastWins : Bool
1414 }
1515
1616 private var queue : [ QueuedOperation ] = [ ]
1717
1818 /// Runs the given operation serially.
19- /// - If canCoalesce is false: operation always executes
20- /// - If canCoalesce is true: may be skipped if superseded by a later coalescable operation
21- func run( canCoalesce : Bool , operation: @Sendable @escaping ( ) async -> Void ) async {
19+ /// - If lastWins is false: operation always executes
20+ /// - If lastWins is true: may be skipped if superseded by a later last-wins operation
21+ func run( lastWins : Bool , operation: @Sendable @escaping ( ) async -> Void ) async {
2222 await withCheckedContinuation { continuation in
23- queue. append ( QueuedOperation ( operation: operation, continuation: continuation, canCoalesce : canCoalesce ) )
23+ queue. append ( QueuedOperation ( operation: operation, continuation: continuation, lastWins : lastWins ) )
2424
2525 if currentTask == nil {
2626 processNext ( )
@@ -36,34 +36,34 @@ internal actor AsyncUnifiedQueue {
3636
3737 // Find the next batch to execute
3838 // A batch is either:
39- // 1. A single non-coalescable operation, OR
40- // 2. Consecutive coalescable operations (we execute only the last one)
39+ // 1. A single non-last-wins operation, OR
40+ // 2. Consecutive last-wins operations (we execute only the last one)
4141
4242 let firstOp = queue [ 0 ]
4343
44- if !firstOp. canCoalesce {
45- // Non-coalescable operation: execute it immediately
44+ if !firstOp. lastWins {
45+ // Non-last-wins operation: execute it immediately
4646 let op = queue. removeFirst ( )
4747 currentTask = Task { [ weak self] in
4848 await op. operation ( )
4949 op. continuation. resume ( )
5050 await self ? . processNext ( )
5151 }
5252 } else {
53- // Coalescable operation: find all consecutive coalescable ops
54- var coalescableCount = 0
53+ // Last-wins operation: find all consecutive last-wins ops
54+ var lastWinsCount = 0
5555 for op in queue {
56- if op. canCoalesce {
57- coalescableCount += 1
56+ if op. lastWins {
57+ lastWinsCount += 1
5858 } else {
5959 break
6060 }
6161 }
6262
63- // Execute only the last one in the coalescable batch
64- let toSkip = Array ( queue. prefix ( coalescableCount - 1 ) )
65- let toExecute = queue [ coalescableCount - 1 ]
66- queue. removeFirst ( coalescableCount )
63+ // Execute only the last one in the last-wins batch
64+ let toSkip = Array ( queue. prefix ( lastWinsCount - 1 ) )
65+ let toExecute = queue [ lastWinsCount - 1 ]
66+ queue. removeFirst ( lastWinsCount )
6767
6868 currentTask = Task { [ weak self] in
6969 await toExecute. operation ( )
0 commit comments