04 septiembre 2008

Multihilos en xHarbour - Parte VI

En estas primeras entregas sobre los multihilos de xHarbour, he hablado de funciones para crear un nuevo hilo, para sincronizar ejecuciones y para sincronizar accesos a recursos.

Sin embargo, puede suceder que tengamos un hilo al que necesitamos finalizar su ejecución porque no se comporta como esperábamos.
Para eso existen 2 funciones. Stopthread y Killthread.
Además, junto con Stopthread, existe una función para sincronizar la finalización del thread con el thread que lo está finalizando.

Stopthread

Sirve para detener la ejecución de un thread de forma amigable, marcando al thread para que se cierre cuando llegue a uno de los puntos de control.
Los puntos de interrupción son:
  • antes y después de un acceso a disco.
  • antes y después de acceso a TCP/IP.
  • antes y después de llamadas a bloqueos.
  • cada vez que finaliza la ejecución de una función PRG, codebloc o macro.
  • cada 5000 ejecuciones de PCODE dentro de un mismo PRG.
Un thread no puede ser detenido amigablemente cuando esta:
  • esperando por un mutex.
  • esperando por conexión o datos de TCP/IP.
  • mientras ejecuta funciones de C o de PRG compilado en C nativo, que quedan en un loop infinito o muy largo.

Killthread

En general hay que evitar el uso de esta función, siempre hay que tratar de finalizar los threads amigablemente.
Windows en su documentación indica que se evite su uso porque puede dejar incluso registros del kernel en estado incorrecto si al matar el thread el proceso esta ejecutando una función en modo kernel.
También la documentación dice que si el thread tiene un bloqueo, este podría no ser desbloqueado o no ser avisados otros threads de que el mutex esta disponible.

Nos encontramos ante la disyuntiva de matar o no a un thread que no responde.
Si no lo matamos, no podremos finalizar la ejecución.
Si lo matamos, quizás tampoco podamos finalizarla.

Por este motivo, la función Killthread inicialmente marca al thread que se le indica para que se cierre amigablemente, si ya esta marcado entonces sí se lo mata.

En conclusión. Hay que tratar por todos los medios de detener los threads amigablemente, para esto es necesario diseñar el código pensando en incluir puntos de interrupción o de control, si fuera necesario, para ayudar a finalizar el/los threads por las buenas.

Jointhread

Esta función se complementa con Stopthread permitiendo sincronizar la finalización del thread.
Se usa para esperar a que el thread indicado termine su ejecución.

Ejemplo:


Procedure Main()
Local thThread

cls
@8,10 say "Presione una tecla para parar el hilo"
thThread := StartThread( @Work() )
StartThread( @Join(), thThread )

inkey(0)
StopThread( thThread )
WaitForThreads()
Return

Procedure Work()
Local aStat := "\|/-", nStat := 1
do while .t.
  DevOut( "Trabajando ... "+aStat[nStat],,10,10)
  if ++nStat > 4
    nStat := 1
  endif
enddo
return

Procedure Join( thThread )
DevOut("Esperando que finalize el thread de trabajo",,12,10)
JoinThread( thThread )
DevOut("El thread de trabajo ha finalizado correctamente",,12,10)
return

01 septiembre 2008

Sobre la Reunión del 30 de Agosto 2008

En primer lugar agradecer el aliento y los comentarios recibidos. Tambien la presencia de todos los que se pudieron acercarce, en especial a aquellos que llegaron de lejos o de países vecinos.

Tuvimos un ambiente de total camaradería y literaltemte nos encerramos en la reunión, a tal punto que ni siquiera fuimos a almorzar (de 9 a 19). Es que había mucho interes.

Respecto de los temas tratados, en orden de presentación fueron:
  • Paradigmas: una charla de Gustavo Valentin acerca de los paradigmas y como afectan la forma en que programamos.
  • Objetos: Walter explicó los conceptos básicos de objetos partiendo de un mini programa que no los tenía y llevandolo en una serie de modificaciones a uno que sí los tenía.
  • Impresoras Fiscales: Walter y Gustavo contaron que es y como funciona una impresora fiscal, la forma de comunicación y los programas que ellos utilizan. Luego se generó un debate entre los que estan necesitados de implementar impresora fiscal en sus programas y, con la donación de código por parte de softmagic quedaron en realizar una clase tanto para epson como para hasar.
  • Hash: si bien no estaba en la agenda de la reunión surgió espontaneamente. Walter nos explicó como inicializar un hash y luego se generó un debate sobre los diferente lugares donde utilizarlo. Fué la frutilla del postre.
  • Se habló de hacer la reunión mas seguido.