c++ boost boost-asio

c++ - Boost asio-detener io_service



boost-asio (1)

Estoy usando boost :: asio para hacer una colección de paquetes UDP muy básica. El objeto io_service se crea una instancia en un subproceso de trabajo, y se llama a io_service.run () desde ese subproceso. Mi problema es conseguir que io_service.run () regrese cuando termine de recolectar los paquetes.

No tengo claro qué métodos de io_service se pueden invocar desde otros hilos cuando llega el momento de detener mi hilo de trabajo. Tengo una referencia al objeto io_service, y de un hilo diferente hago esta llamada:

ios.dispatch( boost::bind( &udp_server::handle_kill, this ) );

En mi clase udp_server, el controlador para esa función cancela el trabajo pendiente desde un solo boost :: asio :: ip :: udp :: socket y un único boost :: asio :: deadline_timer object. Ambos tienen pendiente el trabajo asincrónico por hacer. En ese momento, llamo a ios.stop ():

void udp_server::handle_kill() { m_socket.cancel(); m_timer.cancel(); m_ios.stop(); }

Sin trabajos pendientes, espero que mi llamada a ios.run () vuelva en este momento, pero esto no sucede.

Entonces, ¿por qué no regresa? La explicación más probable para mí es que no debería llamar a io_service :: dispatch () desde otro hilo. Pero el método dispatch () parece que fue creado para hacer justamente eso: despachar una llamada de función en el hilo en el que io_service :: run () está trabajando. Y parece hacer precisamente eso.

Entonces esto me deja con algunas preguntas relacionadas:

  1. ¿Estoy usando io_service :: dispatch () correctamente?
  2. Si se cancelan todas las tareas, ¿hay alguna razón por la que io_service :: run () no deba regresar?
  3. socket :: upd :: cancel () no parece ser la forma correcta de cerrar un socket y cancelar todo el trabajo. ¿Cuál es la manera correcta?

asio se está comportando bastante bien para mí, pero necesito entender mejor este poco de arquitectura.

Más datos

socket :: udp :: cancel () es aparentemente una operación no compatible en un socket abierto bajo Win32 - por lo que esta operación falla lanzando una excepción - que de hecho causa una salida de io_service :: run (), pero definitivamente no es el deseado salida.

socket :: udp :: close () no parece cancelar la tarea pendiente async_receive_from (), por lo que al llamarlo en lugar de socket :: udp :: cancel () parece dejar el hilo en algún lugar dentro de io_service :: run ().


Invocar io_service::stop desde otro subproceso es seguro, esto está bien descrito en la documentación

Seguridad de subprocesos

Objetos distintos : seguro.

Objetos compartidos : seguro, con la excepción de que llamar a reiniciar () mientras hay ejecuciones sin ejecutar run (), run_one (), poll () o poll_one () da como resultado un comportamiento indefinido.

como indican los comentarios a su pregunta, realmente necesita reducir esto a un ejemplo reproducible.