Skip to content

Instantly share code, notes, and snippets.

@NikolaiRuhe
Created June 3, 2022 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NikolaiRuhe/0f41cf5d223f751e35ab9d6a98093e63 to your computer and use it in GitHub Desktop.
Save NikolaiRuhe/0f41cf5d223f751e35ab9d6a98093e63 to your computer and use it in GitHub Desktop.
/// A type that synchronizes progress of two tasks.
///
/// After setup, two tasks should eventually call the `join` function. The
/// first task will suspend until the second task arrives and calls `join` as
/// well. Both tasks resume normally after that.
public final actor TaskRendezvous: Sendable {
private var completion: CheckedContinuation<Void, Error>? = nil
/// Suspends until a second task calls `join()` on this instance.
public func join() async throws {
return try await withCheckedThrowingContinuation { newCompletion in
if let oldCompletion = completion {
self.completion = nil
oldCompletion.resume()
newCompletion.resume()
} else {
self.completion = newCompletion
}
}
}
/// Lets two tasks synchronize so that both perform the closure at the same
/// time.
///
/// 1. Waits until a second task joined.
/// 2. Performs the passed closure while the other task performs its closure.
/// 3. Waits again for the second task to complete its closure.
public func meet<T>(_ perform: () async throws -> T) async throws -> T {
try await join()
let result = try await perform()
try await join()
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment