pub fn detached_with_priority(
priority: TaskPriority,
body: impl FnOnce() + Send + 'static,
) -> TaskExpand description
Run body as a detached Swift Task at a chosen priority.
The closure runs on Swift’s global concurrent executor, so it must be Send
and must not touch anything that wants the main thread — which is most of
SwiftUI. It is FnOnce, because a task runs its body exactly once and owns
it: values can be moved in, and the closure is dropped as soon as it returns.
A panic inside it is caught and reported rather than unwound into the Swift async frame, where there is no landing pad; the task still completes.
As many at once as you like. swift_task_create’s fifth argument is the
closure context and the entry receives it in x20, so each task carries its
own closure — unlike the .task modifier, whose async closure is handed back
the context SwiftUI was given and so has to live in one of three fixed
slots. crate::asyncfn describes that ceiling; this is the same machinery
without it.
let work = runtime::detached(move || {
// …on a cooperative thread…
});
work.wait();§Two things this got wrong, both worth knowing
swift_task_create faults inside itself when either is wrong, which is a
long way from the mistake. Both were found by breaking on the real call in a
Swift binary and reading the registers.
-
The flags are not zero.
Task.detachedpasses1 << 12—Task_EnqueueJob— which makesswift_task_createschedule the task itself. Passing zero and callingswift_task_enqueueafterwards is not the same thing. -
$sytNis not()’s metadata. It is the full metadata record, whose first word is the value witness table; the metadata address point is eight bytes further on. The runtime reads the result type’s value witnesses to size the future, so an address eight bytes low reads a function pointer as a size.crate::abi::resolve_type_by_mangled_namereturns the address point, which is what Swift passes.The empty tuple is special in this, and it is worth saying so before someone generalises the lesson:
$sSiN,$sSSN,$sSbNand$sSdNwere checked against the same lookup and are exactly the address points, which is why the rest of this crate uses them directly. A tuple has no nominal descriptor, so its metadata symbol names a different thing.