Il modulo xtime

Il modulo ntk.wrap.xtime (TODO: replicato in ntk.lib.xtime, perché? Da rimuovere?) risponde al problema dell'uso di sleep in un ambiente di multithread cooperativo.

Quando un microthread ha la necessità di attendere alcuni istanti prima di eseguire una certa azione, come lo fa?
Supponiamo si vuole attendere una certa condizione.

Può eseguire

    while not my_condition():
        pass

Questa è una cosidetta busy-wait. Il sistema viene appesantito, perché fino a quando la condizione non diventa vera il processo impegna la CPU.

Di norma si evita questo spreco inserendo dei piccoli sleep. Ad esempio

    while not my_condition():
        time.sleep(0.01)

Durante questa attesa la CPU non è impegnata. Soltanto una volta ogni 0.01 secondi, che per il processore è molto tempo, fa qualcosa per verificare se la condizione è divenuta vera.
Questa non è più una busy-wait, nel senso che l'intero sistema non viene appesantito. Ma in un ambiente di microthread cooperativi, questo approccio non istruisce lo schedulatore di passare il comando ad altri microthread. Così, anche se il sistema appare scarico, il nostro programma non va avanti.

Va quindi aggiunta una chiamata alla stackless.schedule, che nel nostro programma è nel metodo micro.micro_block().

    while not my_condition():
        time.sleep(0.01)
        micro.micro_block()

Nota: la chiamata a time.sleep resta necessaria, altrimenti ritorneremo ancora ad una situazione di busy-wait.

Qui ci si trova davanti ad una scelta. Quanto tempo aspettare nella chiamata bloccante time.sleep?
Se la verifica della condizione è molto impegnativa, allora un tempo basso nella sleep è controproducente per l'intero sistema. Infatti ogni pochi istanti la CPU viene impegnata per verificare la condizione, mentre forse sarebbe sufficiente al programma effettuare una verifica ad intervalli più ampi.
Si sarebbe portati quindi a usare un tempo alto nella sleep. Ma questa chiamata è bloccante per tutto il programma, quindi un tempo alto ostacola inutilmente il procedere degli altri microthread.

Se invece la verifica della condizione risultasse non impegnativa, allora usare un tempo basso sarebbe la risposta ottimale.

Il modulo xtime facilita questo lavoro implementando una funzione swait che automaticamente intervalla uno sleep di 0.001 secondi con una chiamata micro_block fino a quando non è passato il tempo richiesto. La verifica da fare è poco onerosa, si tratta di leggere l'ora del sistema.

Notare inoltre che nel modulo xtime sia la funzione swait sia la funzione time usano come unità il millisecondo, invece del secondo come nel modulo standard time. (TODO: C'è un motivo particolare?)

In conclusione: