On 2020-05-09 04:02, connor horman via Std-Proposals wrote:
> Currently in the C++ language, it is undefined behaviour to have an
> infinite loop without observable side effects. While this is nice on
> paper, it has a few issues. Any time you need to loop forever, you
> basically need to insert a (potentially costly) side effect. This
> applies any time you need are, say, running a game on a old console, and
> just need to spin while waiting for interrupts to do stuff (same with an
> os kernel). This results in requiring assembly to so this, or maybe
> insert an instruction to wait for an interrupt in a loop (both llvm and
> gcc allow the volatile specifier in an assembly declaration, which is
> treated as observable, so x86_64 code could use hlt (in CPL=0), 65816
> could WAI). This, however, seems to violate one of C++'s core
> principles, that there is no lower level language.
> A further case would be an init process on linux, which cannot terminate
> (doing so results in a kernel panic), nor can just call hlt in a loop,
> as that's one way to get a #GP which probably translates to SIGILL. Once
> an init process is done setting up, it could want to just spin forever,
> and do so using as little system resources as possible. The logical idea
> would be just for(;;) std::this_thread::yield();, but that would be UB
> as yield() is not observable (correct me if I'm wrong).
yield() is potentially observable because it may result in execution of
a thread that has observable behavior.
> Having the ability to spin forever, without wasting time actually doing
> stuff, seems like a reasonable thing to have in low-level code, so its
> very curious (and in many cases, annoying) that you cannot actually do
> this in real code that might have to.
I don't believe you really are spinning forever, as that would be a
rather useless program. Every time you say you're spinning *waiting for
something*, you already have a termination condition - it's when that
something happens. You may have phrased that weirdly in the code, which
makes it look like an infinite loop, but you should be able to do it the
For a SNES Game (on a 65816). The actual thing I'm "waiting" for in some cases is a power down or a RESET. Both of which cannot be detected programatically, nor triggered programatically. For the most part I'm waiting for an interrupt to do stuff in that interrupt. When I receive a VBLANK NMI, I have to do all the dma transfers to within the interrupt handler (in case I overrun the VBLANK time frame, the FBLANK is still set until I use RTI). Once I return from that interrupt, there is nothing more for the main "thread" to do, except wait for the next one or RESET.
For example, if you're waiting for an interrupt, then in terms of your
program you must be waiting until a std::sig_atomic_t variable becomes
true, and set that variable to true in the signal handler.
I'm not waiting for an interrupt to continue, I'm waiting for an interrupt because there is nothing else to do but handle VBLANKs and wait for a shutdown or RESET. Literally anything else that needs to be done is (and can only be) done within the interrupt handler, so the thing the main thread has to do is simply spin. "Waiting" for interrupts in this case simple means I'm doing something slightly smarter in this case to reduce power (by disabling the system clock until an interrupt is recieved).
This is also somewhat common at the end of an embedded program. Spin forever until the processor resets or is shut down.
Std-Proposals mailing list