# \[Pitch\] Task Priority Escalation APIs

**URL:** <https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702>\
**Category:** Pitches\
**Tags:** concurrency\
**Created:** [February 6, 2025, 11:26pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702 "2025-02-06T23:26:14Z")\
**Posts on this page:** 9\
**Page:** 2

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [February 14, 2025, 2:08am UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/21 "2025-02-14T02:08:31Z")

</div>

The `UnsafeCurrentTask` overload is really just there for completeness.

You _COULD_ use it in some weird situations and we try to not randomly leave off APIs from the various accessors to task just because, so it's there...

Is it a great idea to use? Probably not.

Technically you could use it to boost the priority of a task from the inside of the task (?!) which is pretty unusual but could be done:

```swift
// VERY weird, don't do this please...?
Task { 
  if rememberedThisIsVeryImportant() {
    withUnsafeCurrentTask { 
      Task.escalatePriority(of: $0, to: .high)
    }
  }
}

```

It's pretty weird and I would recommend against such random self escalations... but I could imagine that maybe you'd get some callback somewhere and may need to escalate the task you originally entered a function with or something...

In any case, it is possible to use correctly if very careful, so I think it belongs in this proposal.

---

<div class="post-metadata">

**Author:** ![ph1ps](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ph1ps/32/35459_2.png) [@ph1ps](https://forums.swift.org/u/ph1ps)\
**Post date:** [February 20, 2025, 2:09pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/22 "2025-02-20T14:09:36Z")

</div>

What came to my mind, after trying this out:

> [@jamieQ](#):
>
> the cancel handler is named `onCancel` and not `onCanceled`, which makes me wonder if there is a more-aligned naming choice to be made. `onPriorityEscalation` or just `onEscalation` if the implicit context is sufficient? or maybe this new one has made the better choice and cancellation would ideally be changed?

Minor remark, but I agree with this. Could be more aligned here.

> [@ktoso](#):
>
> ```swift
> public func withTaskPriorityEscalationHandler<T, E>(
> operation: () async throws(E) -> T,
> onPriorityEscalated handler: @Sendable (TaskPriority) -> Void,
> isolation: isolated (any Actor)? = #isolation
> ) async throws(E) -> T
> 
> ```

I think the isolation parameter placement is a bit unfortunate but so is it with `withTaskCancellationHandler`. If you want to pass along a specific isolation, you lose the trailing closure sugar.

Nevertheless, I think this is a great addition. With the combination of the mentioned child task handlers and being able to escalate those as well in the future, I think it should finally be possible to implement AsyncQueue/AsyncLimiter/... without priority inversion.

---

<div class="post-metadata">

**Author:** ![SlugFiller](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slugfiller/32/33973_2.png) [@SlugFiller](https://forums.swift.org/u/SlugFiller)\
**Post date:** [February 20, 2025, 6:09pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/23 "2025-02-20T18:09:55Z")

</div>

Am I the only one who feels this is just a huge XY problem?

The example issue is `merge` from `swift-async-algorithms` in which you can't create a structured task which has a lifetime which matches the `merge` operation.

Using current tools, this could be solved by having `merge` receive a `TaskGroup` parameter, which would determine the lifetime of the contained tasks (and hence, the `merge`d stream). If you read a bit about structured tasks/nurseries, you'd realize that's how it's _supposed_ to be used. However, this originates from garbage-collected languages, in which lifetimes must be made explicit.

A correct solution to the problem would be structured tasks of which lifetime is associated with a parent structure/class, relying on ARC. This would require [asynchronous deinitializers](https://forums.swift.org/t/pitch-syncconsumable/74310).

In other words, this entire pitch is basically trying to get structured concurrency without using structured concurrency. In use cases where it's entirely appropriate to use structured concurrency. Instead of trying to figure out how to make structured concurrency work.

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [February 25, 2025, 2:25am UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/24 "2025-02-25T02:25:23Z")

</div>

The proposal is now in review, so it'd be best to provide feedback in the official review thread @SlugFiller: [SE-0462: Task Priority Escalation APIs](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997)

I can answer here though: our structured concurrency primitives are not powerful enough yet, e.g. we'd like to share a task group into child tasks and be able to add tasks into it from them -- we don't have a model for this yet where it would not trigger concurrency safety errors, and it'll require much more work in the typesystem and library to support these. We'd also be able to get rid of the `with...` methods for task groups along this work... but for now we need to support escalation with existing tasks, and this functionality _has existed_ but was internal to Swift, we're making it available to low-level concurrency library authors, which does not preclude continued improvements in the structured concurrency story.

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [February 25, 2025, 12:34pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/25 "2025-02-25T12:34:45Z")

</div>

As the author of the current `merge` implementation, I do agree that the unstructured task here is not what I want to use but it is the only possibility as Konrad noted. We can't currently add a child task to the caller. Furthermore, we would need that child task to be awaited after the iteration to make sure everything is cleaned up.

> [@SlugFiller](#):
>
> A correct solution to the problem would be structured tasks of which lifetime is associated with a parent structure/class, relying on ARC. This would require [asynchronous deinitializers](https://forums.swift.org/t/pitch-syncconsumable/74310).

Using ARC to manage lifetimes is not a correct solution either for two reasons:

- First, the clean up of async sequences might be async itself e.g. closing a file descriptor. This can't be done in `deinit`s since those are sync.
- Even if we had async `deinit`s using them to clean up resources is incredibly brittle and can lead to security problems since `deinit`s on classes run at arbitrary times. That's why in general, we prefer to use `with-style` methods in the ecosystem to have scoped lifetime of resources

---

<div class="post-metadata">

**Author:** ![SlugFiller](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slugfiller/32/33973_2.png) [@SlugFiller](https://forums.swift.org/u/SlugFiller)\
**Post date:** [February 25, 2025, 9:57pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/26 "2025-02-25T21:57:13Z")

</div>

> [@FranzBusch](#):
>
> This can't be done in `deinit`s since those are sync

Hence the need for a new language feature.

> [@FranzBusch](#):
>
> `deinit`s on classes run at arbitrary times

This I have to disagree with. One of the main advantages of ARC over GC is that it's predictable. It is not arbitrary, not brittle, and would not lead to security problems. RIAA is a tried and true method for secure and predictable resource management and scoping, and ARC is an efficient and easy to use RIAA implementation.

IMO `with-style` methods are more of a disease of the current ecosystem, and not something to strive for. It mimics the approach of garbage-collected languages, despite the fact that _not_ being garbage-collected is one of Swift's greatest strengths. And it carries the clear disadvantage that the scope is limited to function/code scoping, and cannot be attached to other lifetimes, like structs, nor returned to a parent scope. With the extra disadvantage of using closures to mimic blocks, thereby losing access to block controls like `break` or `continue` inside the closure.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [February 25, 2025, 10:25pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/27 "2025-02-25T22:25:39Z")

</div>

I have experience converting codebases that rely on object lifetime to instead use manual invalidation. I can certainly attest that under ARC it is unpredictable when any escapable reference type will be deinitialized. This becomes even more of an issue when the reference can escape to another thread.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [February 25, 2025, 11:41pm UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/28 "2025-02-25T23:41:29Z")

</div>

Hi y'all, can discussion about this proposal be directed to the active [review thread](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997)?

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [February 26, 2025, 12:16am UTC](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702/29 "2025-02-26T00:16:50Z")

</div>

Closed on February 26, 2025, 12:16am UTC



[Previous page](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702.md?page=1)
