Created
June 13, 2022 08:13
-
-
Save NikolaiRuhe/c98005245d7b6e25328752cf0680675c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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