= 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: * se la condizione da verificare è poco onerosa, intervallarla con una chiamata a {{{time.sleep}}} con un tempo basso espresso in secondi e una chiamata a {{{micro_block}}}; * se la condizione da verificare è molto onerosa, intervallarla con una chiamata a {{{xtime.swait}}} con un tempo più alto espresso in millisecondi; * se non ci sono condizioni da verificare, ma solo si vuole attendere un certo tempo, usare {{{xtime.swait}}} con il tempo esatto che si vuole attendere espresso in millisecondi.