Garbage Collection en VFP

From codeWiki
Jump to: navigation, search

Por: VictorEspina


La definicion clasica de Garbage Collection indica que es un procedimiento mediante el cual se libera memoria que estaba ocupada por objetos que ya no estan en uso[1]. Esta definición excluye otros recursos como apuntadores, handles de conexión, archivos, etc, que pudieran haber estado en uso por el objeto que se esta liberando, usando para estos casos otros metodos tales como Destroy o Finalize.


Dado que VFP implementa su propio garbage collector y tambien implementa el metodo Destroy en cada objeto, pareciera que no habría mucha cabida para un garbage collector personalizado. Sin embargo, en nuestro dia a dia nos encontramos con situaciones en las que necesitamos ejecutar un cierto código ANTES que un objeto pueda ser liberado, tal como liberar referencias u otros recursos consumidos por el objeto.


Normalmente este código debería ir dentro del evento Destroy del objeto, pero esto presenta un problema: el evento Destroy solo es invocado si el objeto esta siendo "destruido", pero, si existe alguna referencia externa a dicho objeto, el mismo no podrá ser destruido y por ende el evento Detroy nunca sera invocado. Supongo que, como todo en VFP, existen muchas formas de resolver este problema. En mi caso, decidi ampliar el concepto del garbage collector a fin de implementar un metodo llamado collectGarbage en todas mis clases, cuya función es la de liberar cualquier recurso o referencia establecida por el objeto antes de proceder a su destrucción.


El mecanismo funciona así:

  • Cada clase debe tener un metodo llamado collectGarbage el cual contendrá el código necesario para liberar todas las referencias y otros recursos consumidos por el objeto
  • Al momento de cerrar un formulario, se invoca una función llamada collectGarbage que invoca el metodo collectGarbage del objeto indicado y de todos los objetos contenidos en el mismo.


La función determina si cada objeto evaluado contiene el metodo collectGarbage antes de invocarlo, lo cual es bien comodo pues no nos obliga a definir el metodo collectGarbage en todas nuestras clases antes de poder beneficiarnos de la función. Como implementamos la función en nuestras aplicaciones?

  1. Anade la función collectGarbage a alguna de las librerías de tu aplicación
  2. Si usas una clase base para tus formularios, coloca el código collectGarbage(THISFORM) en el evento Destroy de la clase base; de lo contrario, te tocara colocar el código en cada uno de tus formularios.
  3. En las clases donde desees realizar labores de limpieza, anade un metodo de nombre collectGarbage y coloca allí el código de limpieza


Aqui les dejo el código fuente para la función collectGarbage:

* collectGarbage
* Evalua los objetos contenidos en el objeto indicado para determinar
* si los mismos contienen un metodo collectGarbage() para luego 
* invocarlo.
*
PROCEDURE collectGarbage
LPARAMETERS poContainer

*-- Si el objeto contiene el metodo collectGarbage(), se invoca
IF PEMSTATUS(poContainer,"collectGarbage",5)
 poContainer.collectGarbage()
ENDIF

*-- Si el objete es un contenedor, se invoca el metodo en todos sus objetos
LOCAL cBaseClass
cBaseClass = LOWER(poContainer.baseClass)
DO CASE
   CASE cBaseClass == "pageframe"
        LOCAL oControl
        FOR EACH oControl IN poContainer.Pages
         THIS.collectGarbage(oControl)
        ENDFOR

   CASE cBaseClass == "optiongroup"
        LOCAL oControl
        FOR EACH oControl IN poContainer.Buttons
         THIS.collectGarbage(oControl)
        ENDFOR

   CASE INLIST(cBaseClass,"form","container","page")
        LOCAL oControl
        FOR EACH oControl IN poContainer.Controls
         THIS.collectGarbage(oControl)
        ENDFOR
ENDCASE

ENDPROC
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox