Skip to content

Instantly share code, notes, and snippets.

@robertmryan
Last active June 5, 2024 15:44
Show Gist options
  • Select an option

  • Save robertmryan/bc5712e8c185848962eafe07d5137fa8 to your computer and use it in GitHub Desktop.

Select an option

Save robertmryan/bc5712e8c185848962eafe07d5137fa8 to your computer and use it in GitHub Desktop.
actor Foo {
private var firstTask: Task<Void, Error>?
func performFirstTask() async throws {
// create unstructured concurrency
let task = Task {
try await … // the work associated with first task
}
// save this task for future reference by other functions
firstTask = task
// because this is unstructured concurrency, we need to handle cancelation manually
try await withTaskCancellationHandler {
try await task.value
} onCancel: {
task.cancel()
}
}
private func startOrAwaitFirstTask() async throws {
if let firstTask { // see if first task has been started …
try await firstTask.value // … if so, await it
} else {
try await performFirstTask() // … if not, start it
}
}
func performSecondTask() async throws {
try await startOrAwaitFirstTask()
try await … // the work associated with second task
}
func performThirdTask() async throws {
try await startOrAwaitFirstTask()
try await … // the work associated with third task
}
}
@robertmryan

robertmryan commented Mar 27, 2024

Copy link
Copy Markdown
Author

By the way, note the use of actor to avoid race on firstTask. Alternatively, you could make foo a Sendable type, e.g., a class isolated to some global actor. But you want to avoid races amongst these three tasks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment