2009-04-19 12 views
9

Conozco los principios básicos sobre el uso de corrutinas como base y la implementación de un programador de juguetes. Pero supongo que es una visión simplificada en conjunto sobre los planificadores asincrónicos. Hay un conjunto completo de agujeros que faltan en mis pensamientos.¿Cómo implementar un programador de fibra práctico?

¿Cómo evitar que la CPU ejecute un programador que se está ejecutando inactivo/esperando? Algunas fibras simplemente duermen, otras esperan la entrada del sistema operativo.

Respuesta

6

Necesitará multiplex io operaciones en una interfaz basada en eventos (select/poll), para que pueda aprovechar el sistema operativo para hacer la espera, al tiempo que puede programar otras fibras. select/poll tiene un argumento de tiempo de espera: para las fibras que desean dormir, puede crear una cola de prioridad que use esa opción de select/poll para emular una llamada de espera.

Intentando servir fibras que realizan operaciones de bloqueo (llamadas leer/escribir/dormir, etc.). directamente no funcionará a menos que programe cada fibra en un hilo nativo, lo que supera el propósito.

Consulte http://swtch.com/libtask/ para una implementación en funcionamiento.

+0

libtask se ve bien, pero no parece permitir la programación explícita del usuario de la tarea (no pude encontrar una API para dar la CPU a una tarea en particular).Creo que boost :: context se ve más general, y hay una capa en la parte superior llamada boost :: fiber que implementa los bloqueos entre diferentes tareas – lurscher

0

Desde el punto de vista de la implementación, puede comenzar con una implementación de ciclo de eventos asíncrono. A continuación, puede implementar la programación de fibra además de eso mediante el uso de controladores de eventos asincrónicos para cambiar a la fibra correspondiente.

Una fibra para dormir/esperar solo significa que no está programada en este momento, simplemente cambia al bucle de evento.

Por cierto, si usted está buscando un poco de código real, echar un vistazo a http://svn.cmeerw.net/src/nginetd/trunk/ que todavía está en proceso de trabajo, sino que trata de implementar un planificador de fibra en la parte superior de un bucle de eventos multi-hilo (con Win32/S puertos de terminación o epoll desencadenada por borde de Linux).

5

Probablemente debería echar un vistazo a la familia de funciones setcontext (http://en.wikipedia.org/wiki/Setcontext). Esto significará que dentro de su aplicación deberá volver a implementar todas las funciones que puedan bloquear (leer, escribir, dormir, etc.) en formularios asíncronos y regresar al programador.

Solo la "fibra del planificador" tendrá que esperar en los eventos de finalización usando select(), poll() o epoll(). Esto significa que cuando el programador está inactivo, el proceso estará inactivo en la llamada select/poll/epoll, y no ocupará la CPU.

+0

¿Cómo funciona setcontext comparar en la implementación de todo sin tener que depender de pila de la máquina en absoluto? Podría poner coroutines a esperar hasta que otra coroneta se detenga para imitar una simple llamada. – Cheery

1

Aunque es un poco tarde para responder, me gustaría mencionar que tengo una implementación práctica de una biblioteca de fibra en C, llamada libevfibers.

A pesar de ser un proyecto joven, se usa en producción. Proporciona una solución no solo para operaciones asíncronas clásicas, como leer/escribir un socket, sino que también aborda el sistema de archivos IO de forma no bloqueante. El proyecto aprovecha 3 grandes bibliotecas --- libcoro, libev y libeio.

1

Puede controlar el flujo de control también mediante el uso de corrutinas. Una biblioteca que admite la creación de esos es BOOST.ASIO.

Un buen ejemplo es disponible aquí: Boost Stackful Coroutines

Cuestiones relacionadas