2009-04-19 8 views
9

Conosco le nozioni di base sull'uso delle coroutine come base e sull'implementazione di uno scheduler giocattolo. Ma presumo sia una visione eccessivamente semplificata degli scheduler asincroni. Ci sono un sacco di buchi nei miei pensieri.Come implementare un pratico schedulatore di fibre?

Come mantenere la cpu dall'esecuzione di un pianificatore in esecuzione inattivo/in attesa? Alcune fibre dormono, altre attendono input dal sistema operativo.

risposta

6

Avresti bisogno di multiplex operazioni IO in un'interfaccia basata su eventi (seleziona/sondaggio), in modo da poter sfruttare il sistema operativo per fare l'attesa, pur essendo in grado di pianificare altre fibre. select/poll ha un argomento di timeout - per le fibre che vogliono dormire, è possibile creare una coda di priorità che usa quell'opzione di select/poll per emulare una chiamata a riposo.

Provare a servire le fibre che eseguono operazioni di blocco (chiamate lettura/scrittura/sospensione ecc.). direttamente non funzionerà a meno che non si pianifichi ogni fibra in un thread nativo - che tipo di batte lo scopo.

Vedere http://swtch.com/libtask/ per un'implementazione funzionante.

+0

libtask sembra carino ma non sembra consentire la pianificazione esplicita dell'utente dell'attività (non sono riuscito a trovare un'API per dare cpu a una particolare attività).Penso che boost :: context abbia un aspetto più generale, e in cima c'è un layer chiamato boost :: fiber che implementa i lock tra diversi task – lurscher

0

Da un punto di vista dell'implementazione, è possibile iniziare con un'implementazione asincrona degli eventi. Quindi è possibile implementare semplicemente la pianificazione delle fibre, utilizzando i gestori di eventi asincroni per passare alla fibra corrispondente.

Una fibra in attesa/in attesa significa solo che non è programmata al momento - passa invece al ciclo degli eventi.

A proposito, se siete alla ricerca di un po 'di codice vero e proprio, dare un'occhiata a http://svn.cmeerw.net/src/nginetd/trunk/ che è ancora work in progress, ma cerca di implementare uno scheduler di fibra in cima ad un ciclo multi-threaded evento (con Win32 di I/O porte di completamento o epoll con trigger a bordo di Linux).

5

Probabilmente si dovrebbe dare un'occhiata alla famiglia di funzioni setcontext (http://en.wikipedia.org/wiki/Setcontext). Ciò significa che all'interno dell'applicazione sarà necessario implementare nuovamente tutte le funzioni che potrebbero bloccare (leggere, scrivere, dormire, ecc.) In moduli asincroni e tornare allo scheduler.

Solo la "fibra di pianificazione" attenderà gli eventi di completamento utilizzando select(), poll() o epoll(). Ciò significa che quando lo scheduler è inattivo, il processo verrà sospeso nella chiamata select/poll/epoll e non occuperà la CPU.

+0

Come funziona setContext confronto sull'attuazione tutto senza affidarsi a pila macchina a tutti? Potrei mettere le coroutine in attesa finché un'altra coroutine non smette di imitare la semplice chiamata. – Cheery

1

Anche se è un po 'tardi per rispondere, vorrei menzionare che ho un'implementazione pratica di una libreria di fibre in C, denominata libevfibers.

Nonostante sia un progetto giovane, viene utilizzato in produzione. Fornisce una soluzione non solo alle classiche operazioni asincrone come la lettura/scrittura di un socket, ma indirizza anche il file system IO in modo non bloccante. Il progetto utilizza 3 grandi librerie --- libcoro, libev e libeio.

1

È possibile controllare il controllo anche tramite l'uso di coroutine. Una libreria che supporta la creazione di quelli è BOOST.ASIO.

Un buon esempio è disponibile qui: Boost Stackful Coroutines