I am curious about how the static members of Task work.
For example, here are two static members:
struct Task {
...
static var isCancelled: Bool { get }
// A Boolean value that indicates whether the task should stop executing.
static func checkCancellation() throws
// Throws an error if the task was canceled.
...
}
And a function foo that creates two Task instances and then cancels them.
How does Task.isCancelled determine that t1 has been cancelled but not t2? Similarly, how does Task.checkCancellation determine that t2 has been cancelled but not t1?
Both members are static, and therefore they have no direct access to instances t1 and t2. They must have some indirect access.
How does this work? How does Task.isCancelled find the instance t1?
It is possible to query for cancellation from within a synchronous task, e.g. while iterating over a loop and wanting to check if we should abort its execution by using the static Task.isCancelled property:
extension Task where Success == Never, Failure == Never {
/// Returns `true` if the task is cancelled, and should stop executing.
///
/// Always returns `false` when called from code not currently running inside of a `Task`.
static var isCancelled: Bool { get }
}
This works the same as its instance counterpart, except that if invoked from a context that has no Task available, e.g. if invoked from outside of Swift's concurrency model (e.g. directly from a pthread) a default value is returned. The static isCancelled property is implemented as:
extension Task where Success == Never, Failure == Never {
static var isCancelled: Bool {
withUnsafeCurrentTask { task in
task?.isCancelled ?? false
}
}
}
As folks already explained: the task, just like a thread, is the ācurrent execution contextā and therefore you can āget the current oneā (like you can with threads).
Since it can be unsafe to escape that and we generally donāt need to access it explicitly while running āon itā, the only api to get āthe current oneā is as shown above. Now that we have non escaping types thatād be actually quite possible to make a āget currentā api that would not be unsafe, if we can prevent you from escaping it, because then itāll always be valid since you can only get it while executing on it
Either way, these methods are static because they get the current task, and we did not want you to each for the unsafe api but these single accesses are always safe.
The same goes for task locals ā they also access the current task after all :-)