6 ms·
Cooperative multitasking, like it's 1995 again? No thanks.
by otabdeveloper2 7y ago
Cooperative multitasking, like it's 1995 again?
No thanks.
- zzzcpan 7y agoAsynchronous programming is not cooperative multitasking.
- edflsafoiewq 7y agoHow is it not?
- hathawsh 7y agoThey are very similar. In cooperative multitasking, programs yield the thread to the OS, while async programs yield to the event loop. In both cases, yielding is voluntary. Are there other differences? It's probably quite easy to turn a program written one way into the other. Edit: I just remembered that in cooperative multitasking, it's probably possible for the OS to safely save the program stack pointer, meaning the program doesn't have to unwind its stack when yielding, unlike async programs. Never mind, that makes the two models quite different. However, in practice, programs written for cooperative multitasking really should be structured just like async programs in order to be responsive (so users can, for example, interact with the GUI while downloading files in the background.)
- zzzcpan 7y agoEven conceptually the models are very different, in one control is just given up and regained unpredictably, while in the other one it is programmed, hence asynchronous programming, not multitasking.
- badamp 7y ago> in one control is just given up and regained unpredictably Which one? It’s “cooperative” ie not unpredictable. The points where one can block are predictable and documented explicitly, otherwise how would the programmer know they won’t block forever. The same should hopefully be the case for async/awaitable apis. In fact where async/await will actually give up control are harder to tease out. The differences are really not as big as they would seem.
- zzzcpan 7y agoIn cooperative multitasking you can program when to give up control, not when it is regained. The regaining part is unpredictable. Which introduces a lot of non-determinism to deal with and overhead.
- gpderetta 7y agoIt is regained in exactly the same cases it would be in the async model: when a blocking operation completes and the scheduler resumes the now ready thread. As scheduler is called executor in the async world, while a thread is a coroutines, but the concepts are very similar.
- badamp 7y agoThis is no different than async/await. At some point you await a scheduled primitive, it could be a timer, io readiness, an io completion... and yield to a scheduler. You don’t specify explicitly when you return. These are not tightly coupled coroutines. This is precisely what is going on in cooperative multitasking. I don’t see how this increases overhead to deal with either. Basically, coop multitasking and async/await operate on the exact same execution framework, the latter just gives convenient syntactic support. Perhaps you should see how typescript turns async await into js.
- zzzcpan 7y agoAwait is just syntactic sugar. You do not really await anything. What actually happens is an event handler gets called on an event, where it sets up more event handlers for more events and so on. This is the essence of asynchronous programming. There are no tasks, no yielding, practically no overhead and everything is deterministic (in relation to external events obviously) [1]. The only cooperative multitasking implementations that have the same amount of determinism are those implemented strictly on top of event loops and that lack yielding function, so they cannot really be called cooperative multitasking implementations, as they can't "cooperate". All actual implementations have yielding, do not get control deterministically (dealing with that non-determinism requires stuff like semaphores) and have relatively significant overhead. [1] If implemented with care, not doing syscalls in the middle of async primitives and using fast nearly-O(1) algorithms for timers, etc. it can be incredibly fast. And of course Rust also gives enough room to mess up all that nice determinism.
- gpderetta 7y agoIt is cooperative, so no control is relinquished predictably. The difference is the syntactic limitations of the current async model prevent building abstractions.
- jeremyjh 7y agoTell that to my infinite loop.
- DecoPerson 7y agoWould you mind elaborating on your opinion here? As far as I understand, cooperative is far more efficient than preemptive, but unsuitable for poorly written or untrusted code. I wish to learn and would really appreciate your assistance if you are willing to help.
- hathawsh 7y agoThe key difference is cooperative multitasking lets the program yield the thread anywhere, not just to the event loop like async programming. Arbitrary yielding was a feature that programmers widely abused in the early Windows days. The user would start something in an app that takes some time to complete; the app would freeze for a while, but all other apps remained usable. It was obvious that the programmers, rather than solving the real problem, had sprinkled some yield instructions throughout the program, which allowed the computer to keep working even though the app was unresponsive. It's a good thing that async programming frameworks don't usually allow yielding from arbitrary places.
- creatonez 7y ago>It's a good thing that async programming frameworks don't usually allow yielding from arbitrary places. Well.. await new Promise((res, rej) => { setImmediate(res); }) (In environments without `setImmediate` this is easily shimmed - https://github.com/YuzuJS/setImmediate https://github.com/YuzuJS/setImmediate)
- hathawsh 7y agoTrue. That's the new kind of yield that requires language support and it's only available in async functions. I was referring to what happens when framework or language designers try to allow something like the await keyword in non-async functions; it turns into an epic mess. I know because I tried (as a thought experiment.) :-)
- monocasa 7y agoCooperative multitasking is great within a single application, it's when you don't have preemptive multitasking between applications that you have the problem seen in the early 90s on early MacOS and Win16.
- creatonez 7y agoWhy not?