2012-02-08 12 views
7

Tengo un boost::thread que realiza lecturas sincrónicas en un boost::asio::serial_port. Cuando destruyo una instancia de la clase que contiene ambos, quiero que el subproceso finalice con elegancia incluso si está bloqueado en una llamada de lectura. ¿Cómo puedo hacer esto?Desbloqueo de lectura síncrona en boost :: asio :: serial_port

Al mirar docs, probé cancel, pero funciona solo para lecturas/escrituras asincrónicas. Luego probé close, pero recibí una excepción y no era del tipo de la que se puede recuperar. Tal vez usando send_break o native_handle? (Esto es Windows y la portabilidad no es crítico)

actualización: También probé a stop la io_service pasé al constructor del objeto del puerto serie, pero el read, no fue desbloqueado.

Editar: La excepción es en realidad "capturable", pero no me gustaría poner un bloque try/catch dentro de un destructor, y la refactorización del código para hacer el proceso de apagado fuera del destructor daría lugar a una gran cantidad de cambios en capas superiores. Así que solo iría por esta solución si alguna autoridad de Boost dice que no hay otra manera.

Respuesta

5

No hay forma de desbloquear la lectura síncrona cuando lo solicite.

Hay dos opciones:

  • close/shutdown el puerto y capturar una excepción, que se planteó
  • uso asíncrono lee y cancel ellos, cuando se apaga su aplicación

El el primero, por supuesto, no es una buena idea, porque no se puede distinguir la aplicación de terminación del error.

+2

Y es por eso que impulso :: Asio no se llama Boost :: :) SioAndAsio –

+0

Te refieres a impulsar :: :: asio serial_port no está destinado a ser leído o escrito de forma sincronizada? Fui a leer/escribir sincrónico para evitar el sondeo ... Si me permiten leer y escribir de esa manera, lo que funciona maravillosamente y no pierde ciclos de CPU, deberían ofrecer una manera de terminar con gracia. –

+0

Sí, quería hacer lo mismo hace unos días. –

1

Al final, dices que recibes una excepción que "no era del tipo de la que puedes recuperar".

¿Qué significa esto?

La solución parece ser atrapar la excepción. ¿Por qué no puedes hacer eso?

Para el caso en que desea distinguir entre un error y la terminación del programa, establezca un indicador en la terminación del programa antes del cierre. En el manejador de excepciones (catch), revisa la bandera. Si se establece, maneje como terminación del programa, o maneje como error.

Usted dice que no desea colocar un bloque try/catch dentro de un destructor. Esto me parece un extraño prejuicio, pero está bien, hay otras formas.

  1. Puede permitir que la excepción se propague hasta el final al bloque catch superior que rodea todo el código, y manejarlo allí. (Usted tiene un bloque try/catch que protege su aplicación completa, por supuesto :-)

  2. Otras formas también son posibles ...pero el jefe acaba de caer por

+0

De hecho ignoré la excepción y pulsé continue en el depurador, pero como sucedió dentro de un destructor, me molestó demasiado poner allí un bloque try/catch. Podría refactorizar mi código para hacer esto fuera del destructor, pero esto haría ondear muchas capas de llamadas de destructores y sería bastante molesto. Solo aceptaría esto como una solución de último recurso. Edité mi pregunta en consecuencia. –

+0

Acerca de las excepciones en destructores, [hay trampas] (http://www.parashift.com/c++faq-lite/exceptions.html#faq-17.9). Pero creo que el escenario peligroso mencionado en las preguntas frecuentes no se aplica. Además, pregunté en la lista de correo de boost-users y me dijeron que capturara 'boost :: asio :: error :: operation_aborted', lo que me permite distinguir el apagado del error, creo. Lo probaré y, si funciona, aceptaré tu respuesta. –

+0

Traté de atrapar 'std :: exception' y me encontré con Runtime Check Failure # 0 (no se conservó el valor de ESP o algo así). Me di por vencido y decidí usar async_read y write + Boost evento de Windows equivalente para realizar lecturas y escrituras de bloqueo. –