rastrillo / native Public

Clone
git clone https://amadan.net/rastrillo/native

Plain git — no account needed to clone.

Download

Download this file

1import Foundation
2
3/// Serializes refreshes so bursts of events do not start overlapping fetches.
4/// Calls arriving during a pass wait for a trailing pass that starts after them.
5/// Use one runner per operation: trailing passes reuse the first caller's closure.
6/// Cancelling a waiter does not cancel the shared work. Do not call this runner
7/// recursively from its pass, since that would wait for itself.
8@MainActor
9public final class CoalescedRunner {
10 private var current: Task<Void, Never>?
11 private var queued = false
12
13 public init() {}
14
15 public func run(_ pass: @escaping @MainActor () async -> Void) async {
16 if let current {
17 queued = true
18 await current.value
19 return
20 }
21 let task = Task { @MainActor [weak self] in
22 repeat {
23 self?.queued = false
24 await pass()
25 } while self?.queued == true
26 // No suspension after clearing: a later caller must never attach
27 // to completed work and return without a fresh pass.
28 self?.current = nil
29 }
30 current = task
31 await task.value
32 }
33}
34