# SE-0526: withDeadline

**URL:** <https://forums.swift.org/t/se-0526-withdeadline/85850>\
**Category:** Proposal Reviews\
**Created:** [April 7, 2026, 1:34am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850 "2026-04-07T01:34:31Z")\
**Posts on this page:** 15\
**Page:** 3

<div class="post-metadata">

**Author:** ![al45tair](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/al45tair/32/17985_2.png) [@al45tair](https://forums.swift.org/u/al45tair)\
**Post date:** [April 15, 2026, 4:11pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/41 "2026-04-15T16:11:35Z")

</div>

Generally this looks good, but I do have two specific concerns to do with `Clock`s. The first relates to the part where we say

> These absolute deadlines are composable and nestable to any set scope of a deadline. This means that when more than one `withDeadline` is nested the minimum of the expiration is taken. **If any nested cases are differing clocks the deadline is adjusted to the minimum by aproximating the current deadline with the offset of the proposed expiration.**

Leaving aside for a moment the typo (should be "approximating", not "aproximating"), the issue here is that there is no particular reason that one `Clock` should be readily convertible to another.

This came up in my `SchedulingExecutor` proposal, the first version of which had `convert()` methods on `Clock` that let you perform approximate conversions between clocks, but that is tricky to get right and encodes a number of assumptions about `Clock`s (e.g. it precludes having `Clock`s that are not directly time-based — e.g. vector clocks or testing clocks that you explicitly `tick()`). We changed that proposal to _not_ do that, by letting the `Clock` itself handle scheduling if we didn't explicitly recognise it as one the executor supports.

I'm not sure what the right solution is here, but likely it isn't converting instants between clocks. Maybe _not_ merging the deadlines, but just acting when the first one expires would be sufficient here?

My other concern is this:

> ```swift
> extension Task where Success == Never, Failure == Never {
> public static var currentDeadline: any InstantProtocol? { get }
> }
> 
> extension UnsafeCurrentTask {
> public var deadline: any InstantProtocol? { get }
> }
> 
> ```

Since `InstantProtocol` is generic (and since additionally you don't know the `Clock`) it's not clear to me how useful this will be in practice?

I guess if the deadlines aren't merged, then this method would go away anyway?

---

<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:** [April 16, 2026, 4:01am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/42 "2026-04-16T04:01:45Z")

</div>

> [@al45tair](#):
>
> My other concern is this:
> 
> > ```swift
> > extension Task where Success == Never, Failure == Never {
> > public static var currentDeadline: any InstantProtocol? { get }
> > }
> > 
> > extension UnsafeCurrentTask {
> > public var deadline: any InstantProtocol? { get }
> > }
> > 
> > ```
> 
> Since `InstantProtocol` is generic (and since additionally you don't know the `Clock`) it's not clear to me how useful this will be in practice?
> 
> I guess if the deadlines aren't merged, then this method would go away anyway?

Would a possible alternative here be to ask for the deadline by passing in a clock and we query only _that_ kind of deadline then? We would not compose the different clock deadlines then though, but querying them would require knowing what clock was used...

For propagation it seems like we have to know the clock, or at least the instant type, anyway, so a client making a remote call needs to know if it's a clock they can/must propagate or not... Perhaps this would become `currentDeadline(using: clock) // -> C.Instant` and then we could decide to default it to `currentDeadline(using: .continious) // -> ContinuousClock.Instant`?

I'll admit I am very torn about the generic clocks here, they introduce a lot of complexity and it would be good to explore this some more...

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [April 16, 2026, 12:48pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/43 "2026-04-16T12:48:48Z")

</div>

> [@ktoso](#):
>
> I'll admit I am very torn about the generic clocks here, they introduce a lot of complexity and it would be good to explore this some more...

Could a generic `Deadline` protocol help here? In the simple case the concrete type would probably be some sort of `ContinousClockDeadline` type, but it could also be something else that is more custom, perhaps not even related to a `Clock`. I'm not sure what the protocol requirements would need to include for that.

But the point is that there would be a single `deadline` and you can inspect its type rather than having to pass the correct clock type to get a deadline. Merging deadlines of different types than the standard `ContinousClockDeadline` would be the responsibility of the type implementing `Deadline`; same for serialization for propagation over the network.

> [@ktoso](#):
>
> This is very much an use case of deadlines as well -- to _not rush_ executing things if we know we have a lot of time remaining. You could totally inform scheduling and task priority information in tasks you're creating using this information.

Perhaps it'd also be a good idea to be able to pass this information without automatically triggering a cancellation after the deadline. For instance, if a task is rendering a frame and misses its deadline it'll result in an skipped frame, which is undesirable but you still want it to complete. Kind of a soft deadline.

(And thus perhaps a `Deadline` protocol could have an affordance for doing something else than cancelling the task when the deadline is reached.)

---

<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:** [April 16, 2026, 1:17pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/44 "2026-04-16T13:17:13Z")

</div>

We just added cancellation shields to the language which allow for this “regardless of cancellation” execution, so I don’t think we should do another mechanism to not have cancellation.

I think the semantic of cancelling after exceeding the deadline is right, it’s just that they can be used for other things programmatically as well.

---

<div class="post-metadata">

**Author:** ![al45tair](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/al45tair/32/17985_2.png) [@al45tair](https://forums.swift.org/u/al45tair)\
**Post date:** [April 17, 2026, 2:40pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/45 "2026-04-17T14:40:58Z")

</div>

> [@ktoso](#):
>
> Would a possible alternative here be to ask for the deadline by passing in a clock and we query only _that_ kind of deadline then? We would not compose the different clock deadlines then though, but querying them would require knowing what clock was used...

I wonder if it might be possible to have a `Deadline` type that holds both a reference to the `Clock` and the `Clock.Instant`? Something like

```swift
struct Deadline {
  var clock: any Clock
  var instant: any InstantProtocol
}

```

then you could have

```swift
extension Task where Success == Never, Failure == Never {
  public static var currentDeadline: Deadline? { get }
}

extension UnsafeCurrentTask {
  public var deadline: Deadline? { get }
}

```

I don't know how easy this would be to use in practice — I think you'd want to experiment a bit to try it and see.

---

<div class="post-metadata">

**Author:** ![johannesweiss](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johannesweiss/32/38183_2.png) [@johannesweiss](https://forums.swift.org/u/johannesweiss)\
**Post date:** [April 20, 2026, 1:43pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/46 "2026-04-20T13:43:52Z")

</div>

> In reality you will be adding jitter to deadlines anyway

Yes, but the big issue is that with timer coalescing, your jitter won't matter.

Even if you have two deadlines, say at

- 12:33:44.5678
- 12:33:45.8875

e.g. they're jittered to be just over a second apart from each other. But let's say that they're a minute or so out from right now, then they'll likely be coalesced together which makes them fire at the same time --\> very bad.

> , but your request would be specifically to default the tolerance to 0 right?

Correct, everything but `.zero` presents real issues.

> Coalescing is an idea to save on timer events, but I totally see your example of it achieving the inverse effect by firing at the same time and needing to be serviced then.

I think the idea is to let the main processor remain asleep for longer. Maybe this is an okay-ish default for watchOS apps, maybe maybe (I don't think so but don't have data) even on iOS apps but it's certainly not a good default for most things. If you really want timer coalescing, you can opt into this too. But the default should be safe and "what it says on the tin" IMHO.

> I wonder though if just adding jitter with the existing API is sufficient or not, in your experience with sleep?

No, it's not because the crucial bit is to set `tolerance: .zero`.

---

<div class="post-metadata">

**Author:** ![benlings](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benlings/32/13011_2.png) [@benlings](https://forums.swift.org/u/benlings)\
**Post date:** [April 20, 2026, 9:57pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/47 "2026-04-20T21:57:55Z")

</div>

A Deadline type would be a useful place to hang methods for finding the earlier of two deadlines, or for checking if it’s possible to get the deadline in a format suitable for sending to a different machine.

> [@johannesweiss](#):
>
> I think the idea is to let the main processor remain asleep for longer. Maybe this is an okay-ish default for watchOS apps, maybe maybe (I don't think so but don't have data) even on iOS apps but it's certainly not a good default for most things. If you really want timer coalescing, you can opt into this too. But the default should be safe and "what it says on the tin" IMHO.

The text of [SE-0329](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) does leave a `nil` tolerance as

> Not specifying a tolerance infers to the implementor of the clock that the tolerance is up to the implementation details of that clock to choose an appropriate value.

So I think it would be reasonable for some platforms / process configurations to make this mean zero. I remember when timer coalescing was [introduced](https://developer.apple.com/documentation/foundation/timer#Timer-Tolerance), it was advertised as making a difference to phone and laptop battery life. I can see why it would cause issues in a process serving a large number of clients where it’s more important that load is spread out than concentrated.

---

<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:** [April 21, 2026, 3:35am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/48 "2026-04-21T03:35:53Z")

</div>

Yeah that makes sense, thank you for confirming @johannesweiss.

Personally this sounds like a really compelling argument to default to zero tolerance to me, though it'll be good to hear @Philippe_Hausler and @al45tair's thoughts as well.

---

<div class="post-metadata">

**Author:** ![benlings](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benlings/32/13011_2.png) [@benlings](https://forums.swift.org/u/benlings)\
**Post date:** [April 21, 2026, 7:11am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/49 "2026-04-21T07:11:34Z")

</div>

It seems like there are two populations that want different defaults for this - app developers with a single client want timer coalescing for load concentration, and server developers don’t want it for load spreading. Is it something that could be configured, so that both can get what they want?

---

<div class="post-metadata">

**Author:** ![al45tair](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/al45tair/32/17985_2.png) [@al45tair](https://forums.swift.org/u/al45tair)\
**Post date:** [April 21, 2026, 9:40am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/50 "2026-04-21T09:40:08Z")

</div>

> [@ktoso](#):
>
> Personally this sounds like a really compelling argument to default to zero tolerance to me, though it'll be good to hear @Philippe_Hausler and @al45tair's thoughts as well.

I have some concerns about defaulting to zero, particularly with respect to Windows.

The native Windows executor doesn't do timer coalescing, but it does have to cope with the fact that timer behaviour on Windows is somewhat problematic — specifically if you want to wait for less than 15.625ms, or with a greater accuracy than ±15.625ms, you need to spin, which is expensive. Since that's quite a large quantum, it's very likely that there are legitimate use-cases where spinning will be required, but at the same time we don't want to do it unless we really have to. Most programs likely don't care that much and can tolerate quite a lot of slop in their delays, and being able to specify `nil` to indicate that fact is important as sensible defaults will differ from platform to platform. The native Windows executor, for instance, treats `nil` as a 10% tolerance with a minimum of 15.625ms and a maximum of 100ms. If, on the other hand, you specify a zero tolerance, that may cause the Windows executor to spin for up to 15ms or so, as you've asked for an accurate timeout.

If the argument is that we should use a default of zero _because of coalescing_, I think that's wrong. We need to have a value that means "pick a sensible default", and that should be the default here — `nil` makes sense for that. If coalescing is a problem, we should have a separate way to disable it, and maybe it should be off by default on non-battery-constrained platforms.

---

<div class="post-metadata">

**Author:** ![benlings](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benlings/32/13011_2.png) [@benlings](https://forums.swift.org/u/benlings)\
**Post date:** [April 21, 2026, 9:58am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/51 "2026-04-21T09:58:36Z")

</div>

> [@al45tair](#):
>
> We need to have a value that means "pick a sensible default", and that should be the default here — `nil` makes sense for that.

That is what `nil` is spec’d to mean:

> [@benlings](#):
>
> The text of [SE-0329](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) does leave a `nil` tolerance as
> 
> > Not specifying a tolerance infers to the implementor of the clock that the tolerance is up to the implementation details of that clock to choose an appropriate value.

---

<div class="post-metadata">

**Author:** ![NotTheNHK](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/notthenhk/32/43199_2.png) [@NotTheNHK](https://forums.swift.org/u/NotTheNHK)\
**Post date:** [April 21, 2026, 12:33pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/52 "2026-04-21T12:33:11Z")

</div>

I still think we shouldn’t have separate `underlyingError` and `cause` properties. What was the rationale behind separating the two?

---

<div class="post-metadata">

**Author:** ![johannesweiss](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johannesweiss/32/38183_2.png) [@johannesweiss](https://forums.swift.org/u/johannesweiss)\
**Post date:** [April 21, 2026, 1:52pm UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/53 "2026-04-21T13:52:26Z")

</div>

> specifically if you want to wait for less than 15.625ms, or with a greater accuracy than ±15.625ms, you need to spin, which is expensive.

> If the argument is that we should use a default of zero _because of coalescing_, I think that's wrong. We need to have a value that means "pick a sensible default", and that should be the default here — `nil` makes sense for that. If coalescing is a problem, we should have a separate way to disable it, and maybe it should be off by default on non-battery-constrained platforms.

This is all very fair. Let me reformulate my actual requirements:

I think it is very important that the simplest, plainest invocation does surprise anybody. As in, it's key that

```swift
try await withDeadline(.now() + .seconds(60)) {
   try await stuff()
}

```

does something sensible. This includes:

- No timer coalescing as that'll create a thundering herd out of nowhere
- No 'expensive spinning' or other mechanisms that would give me unnecessary super high precision (this seems to be a Windows-only issue)

In actual production, it's likely that what people actually want it to write something like

```swift
try await withDeadline(.now() + .seconds(60), maxJitter: .seconds(5)) {
   try await stuff()
}

```

which should mean the same but additionally randomise the actual deadline by up to 5 seconds. But if the plain `withDeadline` behaves sensibly, then this can also be syntactical sugar on top which just adds a bit of randomness around the deadline.

---

<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:** [July 1, 2026, 9:52am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/54 "2026-07-01T09:52:52Z")

</div>

Cross ref, the 3rd review is now online: [[Third Review] SE-0526: withDeadline - #9 by NotTheNHK](https://forums.swift.org/t/third-review-se-0526-withdeadline/87787/9)

---

<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:** [July 14, 2026, 2:46am UTC](https://forums.swift.org/t/se-0526-withdeadline/85850/55 "2026-07-14T02:46:43Z")

</div>



[Previous page](https://forums.swift.org/t/se-0526-withdeadline/85850.md?page=2)
