The key thing about 2023-era asynchronous versus 1995-era cooperative multitasking is code readability and conciseness.
Under the hood, I'm expressing the same thing, but Windows 3.1 code was not fun to write. Python / JavaScript, once you wrap your head around it, is. The new semantics are very readable, and rapidly improving too. The old ones were impossible to make readable.
You could argue that it's just syntactic sugar, but it's bloody important syntactic sugar.
That's my point, we still do that. And based on your phrasing we're forgetting it :)
possibly you are using the terms in subtly different ways so it appears that we disagree when we do not
If the OS forcefully switches control it's preemptive.
in the mac os 8 documentation, explaining how mac os 8 only has 'cooperative multitasking', the term is defined in the way i'm using it (https://developer.apple.com/library/archive/documentation/Ca...):
> In programming, a task is simply an independent execution path. On a computer, the system software can handle multiple tasks, which may be applications or even smaller units of execution. For example, the system may execute multiple applications, and each application may have independently executing tasks within it. Each such task has its own stack and register set.
> Multitasking may be either cooperative or preemptive. Cooperative multitasking requires that each task voluntarily give up control so that other tasks can execute. (...)
> The Mac OS 8 operating system implements cooperative multitasking between applications. The Process Manager can keep track of the actions of several applications. However, each application must voluntarily yield its processor time in order for another application to gain it. An application does so by calling WaitNextEvent, which cedes control of the processor until an event occurs that requires the application’s attention.
that is, this requirement that each task have its own stack is not just something i made up; it's been part of common usage for decades, at least in some communities. the particular relevant distinction here is that, because each task has its own stack (or equivalent in something like scheme), multitasking doesn't require restructuring your code, because calling a normal function can yield the cpu. in the specific case of macos this was necessary so that switcher/multifinder/process-manager could multitask mac apps written for previous versions of macos that didn't have multitasking
what term would you propose for what i'm calling 'cooperative multitasking', like forth and mac os 8 and windows 3.1 (https://softwareengineering.stackexchange.com/questions/3507... https://retrocomputing.stackexchange.com/questions/791/how-d...)? this terminology is not absolutely standardized, and i'd be happy to use different terminology in order to be able to communicate productively
also could you please answer my request for clarification in https://news.ycombinator.com/item?id=38861074
Those are implementation details. What's actually happening in all cases is my definition.
> also could you please answer my request for clarification in
Yes, your examples or the 5 million other implementations of event loops. You forgot to add gtk's for example :)
> in the mac os 8 documentation
... and I see no mention of stacks on Wikipedia:
https://en.wikipedia.org/wiki/Cooperative_multitasking
Which lumps in both the explicit event loop style and the syntactic sugar that got added later.
We could throw definitions around till kingdom come like this. And it's not the exact definition that's my problem.
i'll see if i can flesh out the wikipedia article a bit
And why do you think that in the case of an explicit event loop you don't have to yield? You do have to, and have to sort out some way to continue on your own. Which makes the new 'syntactic sugar' approaches much easier of course. Doesn't mean the principle isn't the same and they don't deserve the same name.
Yes, of course you could, since everything beyond, uh, paper tape, next-state table, and current pen-position (or whatever other pieces there are in a theoretical Turing machine) is basically syntactic sugar. Or, IOW, all programming languages higher than assembly are nothing but syntactic sugar. I like syntactic sugar.
(But OTOH, I'm a diabetic. Gotta watch out for that sugar.)
i hear they're concerned about cancer of the semicolon
for (;;) {
int r = GetMessage(&msg, NULL, 0, 0);
if (!r) break;
if (r == -1) croak();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
or, in yeso, for (;;) {
yw_wait(w, 0);
for (yw_event *ev; (ev = yw_get_event(w));) handle_event(ev);
redraw(w);
}
async/await doesn't always hide the event loop in that sense; python asyncio, for example, has a lot of ways to invoke the event loop or parts of it explicitly, which is often necessary for integration with software not written with asyncio in mind. i used to maintain an asyncio cubesat csp protocol stack where we had to do thisto some extent, though, this vitiates the concurrency guarantees you can otherwise get out of async/await. software maintainability comes from knowing that certain things are impossible, and pure async/await can make concurrency guarantees which disappear when a non-async function can invoke the event loop in this way. so i would argue that it goes further than just hiding the event loop. it's like saying that garbage collection is about hiding memory addresses: sort of true, but false in an important sense