Multithreading sui retrocomputer

COME DEFINIRE UN PROTOTHREAD

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