Il vantaggio principale dei protothread rispetto ai thread ordinari è che sono davvero leggeri: tutti i protothread sono eseguiti sullo stesso stack, e il cambio di contesto coincide con il riavvolgimento dello stack.
Ne consegue che definire un protothread ha la stessa complessità di definire una funzione C, a cui vanno aggiunti un “prologo” e un “epilogo”. Lo si fa con le annotazioni MR_PT_THREAD
, seguita dalle macro MR_PTI_BEGIN
e MR_PTI_END
:
MR_PT_THREAD(function) { MR_PTI_BEGIN(); // ... logic ... MR_PTI_YIELD(); // ... logic ... MR_PTI_END(); }
L'assenza dello stack è un vantaggio nei sistemi con stringenti vincoli di memoria, quelli cioè in cui uno stack per un thread potrebbe utilizzare gran parte della memoria disponibile. Invece, con i protothreads, ciò non avviene.
Un protothread richiede solo due byte di memoria per funzionare e tale spazio viene riservato allocando almeno una variabile del tipo mr_protothread
:
mr_protothread functionThread;
Come è possibile notare, nella funzione viene chiamata almeno una volta la funzione MR_PTI_YIELD
. Tale chiamata è necessaria perché, come abbiamo anticipato, si tratta di thread cooperativi e non preventivi: cioè vi è la necessità che il programmatore indichi il punto migliore in cui l'esecuzione può essere bloccata, e da cui riprendere.
Per mandare in esecuzione i thread è sufficiente chiamare (continuamente) la funzione con la seguente sintassi:
while(1) { function(&functionThread); }
Da notare come sia possibile eseguire N
protothread con il medesimo codice, allocando N
variabili di tipo mr_protothread
e richiamando, in sequenza, ognuna di esse:
mr_protothread functionThread1; mr_protothread functionThread2; ... mr_protothread functionThreadN; ... while(1) { function(&functionThread1); function(&functionThread2); ... function(&functionThreadN); }
Vai a COORDINARE I PROTOTHREAD