Skip to content

Instantly share code, notes, and snippets.

@NikolaiRuhe
Created June 13, 2022 08:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NikolaiRuhe/c98005245d7b6e25328752cf0680675c to your computer and use it in GitHub Desktop.
Save NikolaiRuhe/c98005245d7b6e25328752cf0680675c to your computer and use it in GitHub Desktop.
// TaskMeeting
// (c) 2022, Nikolai Ruhe
/// A type that synchronizes progress of two tasks.
public final actor TaskMeeting: Sendable {
private var completion: CheckedContinuation<Void, Error>? = nil
/// This method synchronizes two tasks so that both perform the closure at
/// the same time. Both tasks need to call `rendezvous`.
///
/// 1. Waits until a second task calls `rendezvous`.
/// 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 rendezvous<T>(_ perform: () async throws -> T) async throws -> T {
try await waitForPeer()
let result = try await perform()
try await waitForPeer()
return result
}
/// This method synchronizes the progress of two tasks, so that one task
/// waits for the second task. The first task will suspend until the second
/// task arrives and also calls `waitForPeer`. Both tasks resume normally
/// after that.
public func waitForPeer() async throws {
return try await withCheckedThrowingContinuation { newCompletion in
if let oldCompletion = completion {
self.completion = nil
oldCompletion.resume()
newCompletion.resume()
} else {
self.completion = newCompletion
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment