{{htmlmetatags>metatag-robots=()
metatag-title=(Coordinate the protothreads | Multithreading on retrocomputers)
metatag-keywords=(Multithreading,Commodore 64,Commodore VIC20,Atari,Commodore128,MIDRES Library,6502,6510)
metatag-description=(How to implement fast and efficient multithreading on computers with limited resources.)
metatag-media-og:image=(:mt6502.png)
metatag-og:title=(Coordinate the protothreads | Multithreading on retrocomputers)
metatag-og:description=(How to implement fast and efficient multithreading on computers with limited resources.)
}}
====== Multithreading on retrocomputers ======
===== BLOCKING AND NON-BLOCKING FUNCTIONS =====
A protothread runs inside a single C function and cannot "span" on other functions. It can, of course, call normal C functions but, at the same time, it cannot block inside a called function.
This code, therefore, will never be able to run or compile correctly:
void f( ) {
...
MR_PTI_YIELD();
...
}
MR_PT_THREAD(g) {
...
f();
...
}
This is because protothread ''g()'' will try to block execution when it is in function ''f()'', which itself is not a protothread. To overcome this limit, **a separate protothread can be generated for each potentially blocking function** and, consequently, a variable ''mr_protothread'' is allocated for it.
MR_PT_THREAD(f) {
...
MR_PTI_YIELD();
...
}
mr_protothread fThread;
MR_PT_THREAD(g) {
...
MR_PTI_SPAWN(&fThread, f(&fThread));
...
}
The advantage of this approach is that the blocking is explicit, and therefore **the programmer knows exactly which functions can block** and which ones they cannot block, thus simplifying debugging by simply reading the code.
Move to [[:mt6502:locals|HOW TO MANAGE LOCAL VARIABLES]].