2009-12-06 14 views
6

Estoy usando sockets síncronos asio para leer datos a través de TCP desde un hilo de fondo. Esto está encapsulado en una clase de "servidor".Interrupt boost :: asio synchronous read?

Sin embargo, quiero que el hilo salga cuando se llame al destructor de esta clase. El problema es que una llamada a cualquiera de las funciones de lectura se bloquea, por lo que el hilo no puede ser terminado fácilmente. En Win32 hay una API para eso: WaitForMultipleObjects que haría exactamente lo que quiero.

¿Cómo conseguiría un efecto similar con el impulso?

Respuesta

2

En nuestra aplicación, establecemos la condición de "terminación" y luego usamos una auto conexión al puerto que escucha el hilo para que se despierte, anota la condición de terminación y finaliza.

También podría verificar la implementación de boost: si solo realizan una lectura simple en el socket (es decir, no usan algo como WaitForMultipleObjects internamente) entonces probablemente puedan concluir que no hay nada que simplemente y limpiamente desbloquear la amenaza. Si están esperando en varios objetos (o en un puerto de finalización), podrías cavar para ver si la capacidad de activar el hilo de bloqueo está expuesta al exterior.

Finalmente, podrías matar el hilo, pero tendrás que salir del impulso para hacerlo, y comprender las consecuencias, como los recursos que se cuelgan o se filtran. Si se está cerrando, puede que esto no sea una preocupación, dependiendo de qué más esté haciendo el hilo.

2

No he encontrado una manera fácil de hacer esto. Supuestamente, hay formas de cancelar win32 IOCP, pero no funciona bien en Windows XP. MS lo arregló para Windows Vista y 7. El enfoque recomendado para cancelar asio async_read o async_write es cerrar el socket.

  • [destructor] Observamos que queremos tearDown
  • [destructor] cerrar la toma
  • [destructor] esperamos a los manipuladores de finalización

  • [Terminación] si derribando y que acaba de fracasar debido a que el socket se cerró, notifique al destructor que los manejadores de finalización están terminados.

  • [finalización] devolver inmediatamente.

Tenga cuidado si elige implementar esto. Cerrar el socket es bastante sencillo. 'esperar a los manejadores de finalización' sin embargo es enormemente comprensible. Hay varios casos de esquina sutiles y condiciones de carrera que pueden ocurrir cuando el subproceso del servidor y su destructor interactúan.

Esto fue suficiente que construimos un envoltorio de finalización (similar a io_service::strand sutil sólo para manejar de forma sincrónica cancelando todas las devoluciones de llamada de finalización pendientes.

1

mejor forma de hacerlo es crear un socketpair(), (sea lo que sea en boost::asio jerga), añadir el lector finaliza en el bucle de evento, luego cierra el final del escritor. Se lo despertará inmediatamente con un evento eof en ese socket.

El hilo se debe cerrar voluntariamente.

El desove de la rosca debe en su destructor, tienen el siguiente:

~object() 
{ 
    shutdown_queue.shutdown(); // ask thread to shut down 
    thread.join();    // wait until it does 
} 
-1

Uso socket.cancel(); para finalizar todas las operaciones asincrónicas actuales que bloquean en un socket. Los sockets de cliente pueden necesitar ser eliminados en un bucle. Nunca he tenido que cerrar el servidor de esta manera, pero puede usar shared_from_this() y ejecutar cancel()/close() en un bucle similar a cómo el ejemplo de chat boost async_writes a todos los clientes.

Cuestiones relacionadas