> Your program must be really small and scoped for this to make sense.
to me suggests that it's not really global state if your program has to stay small and scoped. In a sense, your program has just become the context boundary for the state, instead of a function, or class, or database.
I realise that this line of argument effectively leads to the idea that no state is global, but perhaps that gives us a better way to understand the claim that 'global variables can work', which they undoubtedly can. It's fine for a program (or a thread, as in the original article) to be the context which bounds a variable's scope.
Well it's still technically a global state if it's a collection of scoped singletons, it's not much different than having a map of object names and their data as one big global variable, it's just formatted slightly more practically.
I'm the author. You don't exactly need the program to be small, you could do a lot with a small file (under 500 lines) being the only one able to access a global variable. People seem to think it's ok to leak data from your encapsulation when you're using a global which I tried to say is a bad idea in the article.
I've seen code for emulators that is very long functions and a lot of globals; I'd also argue they're OK if your program flow is very stable / predictable and synchronous, and especially older consoles and game engines have predictable phases. Getting information from your "tick" to your "render" stage is a lot easier if you have global state.
Emulators are often emulating "hardware globals", things like machine registers or GPU state where in the thing being emulated there really is only one instance.
That's a single mutable global with all application state, but inside that global are nested structs and the code working on those structs takes essentially a 'this' pointer. This approach works well since it enforces a strictly hierarchical code and data structure with a single root-struct (and also a single root-source-file) at the top.
A useless microbenchmark question: what is faster, accessing a global variable (which has to go through the GOT nowadays) or dereferencing a field in a structure that was passed to you by a pointer (a straightforward register+offset load)?
Your program must be really small and scoped for this to make sense.
Also, kudos for providing so many corner cases to avoid that are non-trivial to formulate.
It feels like one of those "it's not impossible to do right" cases.
I'll just cite one evaluation point from the post:
> It's extremely easy to use incorrectly.