C++26: Trivial infinite loops are no longer undefined behaviour
Thread
Unofficial Hacker News client; not affiliated with Y Combinator.
C++26: Trivial infinite loops are no longer undefined behaviour
Unofficial Hacker News client; not affiliated with Y Combinator.
JoshTriplett · · focus · HN ↗
Insert screaming here.
An infinite loop, with no library calls whatsoever, gets a system call inserted. That's a horrible surprise waiting to happen.
The entire concept of the "forward progress guarantee" is broken. An infinite loop should compile to an infinite loop. Nothing more, nothing less.
amluto · · focus · HN ↗
I admit I’m unconvinced that this is particularly useful.
(I got many other ideas that did not pass my personal smell test.)
raphlinus · · focus · HN ↗
[1]: <a href="https://youtu.be/g9Rgu6YEuqY?si=_l9JwKhjvIdFEDEX&t=3819" rel="nofollow">https://youtu.be/g9Rgu6YEuqY?si=_l9JwKhjvIdFEDEX&t=3819
amluto · · focus · HN ↗
1. Most implementations do not do this automatic cooperative multitasking trick and most users [0] don’t want it done to their code.
2. The fact that a “step” is guaranteed to happen in finite time is far too weak for most use cases. I’ve done plenty of kernel programming, and a lot of kernels are partially or fully cooperative scheduled. Even somewhat long loops need manually inserted preemption points.
3. “Finite” can be a very long time indeed. There are literally competitions to see who can make the largest busy beaver machine.
Put another way, undefined behavior is a sharp line - if code has UB, it has UB and it if doesn’t, it doesn’t. But code being slow is not a sharp line - something can take 1 ns or 1 ms or 1 second or 1 hour or 1 year or 100 years or 1M years, etc.
A scheduler that fails to schedule a runnable thread in finite time is wrong, but so is a scheduler that fails to schedule it for 100 years or for a week. If it merely takes a minute, then whether it’s right or wrong depends on the situation.
So if you’re talking about schedulers (which that part of talk mostly is), then I don’t think the ability to say “infinite loop without side effects are UB, so my scheduler is correct if I assume that all side-effect-free loops are finite” is actually useful.
There are real world examples. At one point, Go only preempted its cooperative threads at certain points, but this was a problem and newer versions of Go can even preempt tight loops. Python, which threads the worst-of-both-worlds middle ground between asynchronous and cooperative preemption, does not allow an infinite loop (in ordinary Python code) to starve other threads.
[0] Most users of C- or Rust-like languages anyway. Quite a few more managed languages (e.g. Go) are the other way around.