448 lines
17 KiB
Plaintext
448 lines
17 KiB
Plaintext
/*
|
||
* $Id$
|
||
*/
|
||
|
||
/*
|
||
* Las siguientes partes son derechos adquiridos de sus autores individuales.
|
||
* www - http://www.harbour-project.org
|
||
*
|
||
* Copyright 2000 Alejandro de G rate <alex_degarate@hotmail.com>
|
||
* Documentaci¢n en Espa¤ol de:
|
||
* Readme, hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(),
|
||
* hb_gcUnlockItem(), hb_gcCollectAll(), hb_gcItemRef(), HB_GCALL()
|
||
*
|
||
* Copyright 2000 brian Brian Hays <bhays@abacuslaw.com>
|
||
* Documentaci¢n en Ingl‚s de:
|
||
* Readme, hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(),
|
||
* hb_gcUnlockItem(), hb_gcCollectAll(), hb_gcItemRef(), HB_GCALL()
|
||
*
|
||
* Vea doc/license.txt por los t‚rminos de la licencia.
|
||
*
|
||
*/
|
||
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* Colector de memoria
|
||
* $CATEGORY$
|
||
* Documento
|
||
* $ONELINER$
|
||
* L‚ame con informaci¢n de la recolecci¢n de memoria.
|
||
* $DESCRIPTION$
|
||
* El recolector de memoria (Garbage Collector ¢ GC) usa la siguiente
|
||
* l¢gica:
|
||
* - primero recolectar todas las ubicaciones de memoria que puedan
|
||
* constituirse en "basura"
|
||
* - luego inspeccionar todas las variables, por si esos bloques est n
|
||
* todav¡a referenciados.
|
||
*
|
||
* Note que s¢lo arrays, objetos y bloques de c¢digo son recolectados
|
||
* porque esos son los £nicos tipos de datos que pueden causar:
|
||
* auto-referencias
|
||
* ( a [1] : = a )
|
||
* ¢ referencias circulares:
|
||
* ( a[1] := b; b[1] := c; c[1] := a )
|
||
* que no pueden ser apropiadamente desasignadas por un simple conteo
|
||
* de referencia.
|
||
*
|
||
* Como todas las variables en Harbour son almacenadas dentro de algunas
|
||
* tablas disponibles (eval stack, tabla de memvars y array de variables
|
||
* est ticas), entonces chequear si la referencia es todav¡a activa es
|
||
* bastante f cil y no requiere ning£n tratamiento especial durante la
|
||
* la asignaci¢n de memoria. Adicionalmente el recolector de memoria
|
||
* inspecciona algunos datos internos usados por la implementaci¢n de
|
||
* objetos de Harbour que tambi‚n almacena algunos valores que pueden
|
||
* contener referencias de memoria. Estos datos son usados para inicia-
|
||
* lizar variables de instancia de la clase, y son almacenadas en
|
||
* variables compartidas por la clase.
|
||
*
|
||
* En casos especiales cuando el valor de una variable de Harbour es
|
||
* almacenada internamente en alg£n area est tica (a nivel de lenguaje
|
||
* C ¢ asembler), por ejemplo SETKEY() almacena bloques de c¢digo que
|
||
* ser n evaluados cuando se presione una tecla, el recolector de
|
||
* memoria no ser capaz de inspeccionar esos valores porque este no
|
||
* conoce su ubicaci¢n. Esto podr¡a ocasionar que algunos bloques de
|
||
* memoria sean liberados prematuramente. Para prevenir la prematura
|
||
* desasignaci¢n de esos bloques ellos deben ser bloqueados para el
|
||
* recolector de memoria.
|
||
*
|
||
* Para ello se definen distintos estados del bloque de memoria:
|
||
*
|
||
* #define HB_GC_UNLOCKED 0 // desbloqueado
|
||
* #define HB_GC_LOCKED 1 // No recolectar el bloque de memoria
|
||
* #define HB_GC_USED_FLAG 2 // bit para la bandera usado/no usado
|
||
*
|
||
* El bloque de memoria puede ser bloqueado con hb_gcLockItem(), m‚todo
|
||
* recomendado si un ¡tem de estructura es usado ¢ con la funci¢n
|
||
* hb_gcLock() si un puntero directo a memoria es usado.
|
||
* El bloque de memoria puede ser desbloqueado por hb_gcUnlockItem() ¢
|
||
* hb_gcUnlock().
|
||
*
|
||
* N¢tese sin embargo que todas las variables pasadas a una funci¢n de
|
||
* bajo nivel son pasadas mediante la pila de evaluaci¢n (eval stack),
|
||
* as¡ ellas no necesitan bloquearse durante la llamada a la funci¢n.
|
||
* El bloqueo puede ser requerido, si un valor pasado es copiado dentro
|
||
* de alg£n rea est tica para hacerla disponible para otras funciones
|
||
* de bajo nivel, llamadas despu‚s de la salida de la funci¢n que
|
||
* almacena el valor. Esto es requerido porque el valor es removido de
|
||
* la pila de evaluaci¢n despu‚s de la llamada a la funci¢n y esta no
|
||
* puede seguir siendo referenciada por otras variables.
|
||
*
|
||
* Sin embargo la inspecci¢n de todas las variables puede ser una
|
||
* operaci¢n de un gran consumo de tiempo. Esto requiere que todos los
|
||
* arrays asignados tengan que ser recorridos a trav‚s de todos sus
|
||
* elementos para encontrar m s arrays.
|
||
* Tambi‚n todos los bloques de c¢digo son inspeccionados, en busca de
|
||
* variables locales separadas que ellos estan referenciando. Por esta
|
||
* esta raz¢n, la busqueda por bloques de memoria no referenciados es
|
||
* realizada durante los estados inactivos.
|
||
*
|
||
* El estado inactivo es el estado cuando no hay un c¢digo real de la
|
||
* aplicaci¢n ejecut ndose. Por ejemplo, el c¢digo del usuario es
|
||
* detenido durante 0.1 segundo por INKEY(0.1) - Harbour esta chequeando
|
||
* s¢lo el teclado durante este tiempo. Esto deja sin embargo suficiente
|
||
* tiempo para muchas otras tareas en segundo plano. Una de esas tareas
|
||
* en segundo plano, puede ser la b£squeda de bloques de memoria no
|
||
* referenciados.
|
||
*
|
||
* Asignando memoria </par>
|
||
* -----------------
|
||
*
|
||
* El recolector de memoria, recoge bloques de memoria asignados con
|
||
* llamadas a la funci¢n hb_gcAlloc(). La memoria asignada por
|
||
* hb_gcAlloc() deber¡a ser liberada con la funci¢n hb_gcFree().
|
||
*
|
||
*
|
||
* Bloqueando memoria </par>
|
||
* ------------------
|
||
*
|
||
* La memoria asignada con hb_gcAlloc() deber¡a ser bloqueada para
|
||
* prevenir una autom tica liberaci¢n como un puntero de memoria si no
|
||
* es almacenado dentro de una variable a nivel de Harbour. Todos los
|
||
* valores de Harbour (items), almacenados internamente en reas
|
||
* est ticas de lenguaje C deben ser bloqueadas.
|
||
* Vea hb_gcLockItem() y hb_gcUnlockItem() para m s informaci¢n.
|
||
*
|
||
*
|
||
* La recoleci¢n de memoria </par>
|
||
* ------------------------
|
||
*
|
||
* Durante la b£squeda de memoria no referenciada, el recolector de
|
||
* memoria (RM) est usando un algoritmo llamado "mark & sweep", marcar
|
||
* y barrer. Este es realizado en tres etapas:
|
||
*
|
||
* 1) Marcar todos los bloques asignados por el RM con un bandera:
|
||
* "sin uso"
|
||
*
|
||
* 2) barrer (buscar) todos los lugares conocidos y limpiar las banderas
|
||
* sin uso por los bloques de memoria que son referenciados all¡;
|
||
*
|
||
* 3) finalizar recolectando por desasignaci¢n de todos los bloques de
|
||
* memoria que a£n estan marcados como sin uso y que no est n bloqueados.
|
||
*
|
||
* Para acelerar las cosas un poco, la etapa de marca es simplificada
|
||
* por la inversi¢n del significado de la bandera "sin uso". Despu‚s de
|
||
* la desasignaci¢n de los bloques sin uso, todos los bloques todav¡a
|
||
* activos son marcados con la bandera "usado" as¡ nosotros podemos
|
||
* invertir el significado de esta bandera al estado "sin uso" en la
|
||
* pr¢xima recoleci¢n.
|
||
* Todos los bloques de memoria nuevos ¢ sin bloquear son autom tica-
|
||
* mente marcados como "sin uso" usando la bandera actual, lo cual
|
||
* asegura que todos los bloques de memoria son marcados con la misma
|
||
* bandera antes de que la etapa de barrido comience.
|
||
*
|
||
* Ver hb_gcCollectAll() y hb_gcItemRef()
|
||
*
|
||
*
|
||
* Llamando al recolector de memoria desde c¢digo Harbour
|
||
* ------------------------------------------------------
|
||
*
|
||
* El RM puede ser llamado directamente desde un programa en Harbour.
|
||
* Esto es £til en situaciones donde no hay estados inactivos
|
||
* disponibles ¢ la aplicaci¢n esta trabajando en un bucle sin
|
||
* interacci¢n con el usuario y hay muchas asignaciones de memoria.
|
||
* Vea HB_GCALL() por una explicaci¢n de como llamar a esta funci¢n
|
||
* desde el c¢digo de Harbour.
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem(),hb_gcCollectAll(),hb_gcItemRef(),HB_GCALL(),HB_IDLESTATE()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcAlloc()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Asigna memoria que ser recolectada por el recolector de memoria.
|
||
* $SYNTAX$
|
||
* #include <hbapi.h>
|
||
* void *hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc );
|
||
* $ARGUMENTS$
|
||
* <ulSize> es el tama¤o solicitado del bloque de memoria.
|
||
*
|
||
* <pCleanupFunc> es un Puntero a la funci¢n HB_GARBAGE_FUNC que ser
|
||
* llamada directamente antes de la liberaci¢n del bloque
|
||
* de memoria sin uso ¢ NULL. Esta funci¢n deber¡a
|
||
* liberar toda otra memoria asignada y almacenada dentro
|
||
* del bloque de memoria.
|
||
* Por ejemplo, esta libera todos los items almacenados dentro del array
|
||
* La funci¢n recibe un s¢lo par metro: el puntero a la memoria asignada
|
||
* por hb_gcAlloc().
|
||
* $RETURNS$
|
||
* Devuelve un puntero a la memoria asignada ¢ esta generar un error
|
||
* interno irrecuperable.
|
||
* $DESCRIPTION$
|
||
* hb_gcAlloc() es usada para asignar la memoria que ser rastreada por
|
||
* el RM. Este permite una apropiada liberaci¢n de memoria en el caso
|
||
* de variables auto-referenciadas ¢ con referencias cruzadas a nivel
|
||
* de Harbour.
|
||
* La memoria asignada con esta funci¢n deber¡a ser liberada con la
|
||
* funci¢n hb_gcFree() ¢ esta ser autom ticamente desasignada por el
|
||
* RM si no esta bloqueada ¢ si no esta referenciada por alguna
|
||
* variable a nivel de Harbour.
|
||
* $EXAMPLES$
|
||
* Vea ../source/vm/arrays.c
|
||
*
|
||
* PHB_BASEARRAY pArr = (PHB_BASEARRAY) :
|
||
* hb_gcAlloc( sizeof( HB_BASEARRAY), ;
|
||
* hb_arrayReleaseGarbage );
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcFree()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Libera la memoria que fu‚ asignada con hb_gcAlloc().
|
||
* $SYNTAX$
|
||
* void hb_gcFree( void *pMemoryPtr );
|
||
* $ARGUMENTS$
|
||
* <pMemoryPtr> es el puntero a la memoria a liberar. Este puntero de
|
||
* memoria debe ser asignado con la funci¢n hb_gcAlloc().
|
||
* $RETURNS$
|
||
* Nada.
|
||
* $DESCRIPTION$
|
||
* La funci¢n hb_gcFree() es usada para liberar la memoria que fu‚
|
||
* asignada con la funci¢n hb_gcAlloc().
|
||
* $EXAMPLES$
|
||
* Vea ../source/vm/arrays.c
|
||
* hb_gcFree( (void *) pBaseArray ); // puntero al array a liberar
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcLockItem(),hb_gcUnlockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcLockItem()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Bloquea la memoria para prevenir la desasignaci¢n por el RM.
|
||
* $SYNTAX$
|
||
* void hb_gcLockItem( HB_ITEM_PTR pItem );
|
||
* $ARGUMENTS$
|
||
* <pItem> es el puntero a la estructura item que ser bloqueada.
|
||
* El item pasado puede ser de cualquier tipo de datos, aunque
|
||
* arrays de objetos y bloques de c¢digos son bloqueados
|
||
* solamente. Otros tipos de datos no necesitan bloqueo, as¡
|
||
* que ellos son simplemente ignorados.
|
||
* $RETURNS$
|
||
* Nada.
|
||
* $DESCRIPTION$
|
||
* La funci¢n hb_gcLockItem() es usada para bloquear el puntero de
|
||
* memoria almacenado en la estructura item pasada. Este suprime la
|
||
* liberaci¢n de memoria si el RM no encuentra alguna referencia a
|
||
* este puntero.
|
||
* El RM almacena un contador de bloqueo y cada llamada a esta funci¢n
|
||
* incrementa el contador. El item es bloqueado si el contador es mayor
|
||
* que cero.
|
||
* $EXAMPLES$
|
||
* Vea ../source/rtl/setkey.c
|
||
* // bloquea un codeblock para prevenir la liberaci¢n por el RM
|
||
* hb_gcLockItem( sk_list_tmp-> pAction );
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcFree(),hb_gcUnlockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcUnlockItem()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Desbloquea la memoria para prevenir la liberaci¢n por el RM
|
||
* $SYNTAX$
|
||
* void hb_gcUnlockItem( HB_ITEM_PTR pItem );
|
||
* $ARGUMENTS$
|
||
* <pItem> es el puntero a la estructura item que ser bloqueada.
|
||
* El item pasado puede ser de cualquier tipo de datos, aunque
|
||
* arrays de objetos y bloques de c¢digos son bloqueados
|
||
* solamente. Otros tipos de datos no necesitan bloqueo as¡
|
||
* que ellos son simplemente ignorados.
|
||
* $RETURNS$
|
||
* Nada.
|
||
* $DESCRIPTION$
|
||
* La funci¢n hb_gcUnlockItem() es usada para desbloquear el puntero de
|
||
* memoria almacenado en la estructura item pasada, que fu‚ previamente
|
||
* bloqueada con una llamada a hb_gcLockItem(). Esto permite liberar
|
||
* la memoria durante la recolecci¢n de memoria sin uso si el RM no
|
||
* encuentra ninguna referencia a este puntero. El RM almacena el
|
||
* contador de bloqueo, cada llamda a esta funci¢n decrementa el
|
||
* contador.
|
||
* Esta funci¢n no libera la memoria almacenada dentro del item,
|
||
* la memoria debe ser desasignada sin embargo durante la recoleci¢n
|
||
* de memoria sin uso m s cercana, si el contador de bloqueo es
|
||
* igual a cero y el puntero de memoria no es referenciado por
|
||
* ninguna variable a nivel de Harbour.
|
||
* $EXAMPLES$
|
||
* Vea ../source/rtl/setkey.c
|
||
* hb_gcUnlockItem( sk_list_tmp-> pAction ); // libera el item
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcCollectAll()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Examina todos los bloques de memoria y libera la memoria sin uso.
|
||
* $SYNTAX$
|
||
* void hb_gcCollectAll( void );
|
||
* $ARGUMENTS$
|
||
* Ninguno.
|
||
* $RETURNS$
|
||
* Nada.
|
||
* $DESCRIPTION$
|
||
* Esta funci¢n examina la pila de evaluaci¢n, las tablas de memvars,
|
||
* el array de variables est ticas y las tablas de clases creadas en
|
||
* busca de bloques de memoria referenciados. Despu‚s de examinar todos
|
||
* los bloques de memoria sin uso y los bloques que no estan bloqueados,
|
||
* son liberados.
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* hb_gcItemRef()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Marca la memoria para prevenir la desasignaci¢n por el RM.
|
||
* $SYNTAX$
|
||
* void hb_gcItemRef( HB_ITEM_PTR pItem );
|
||
* $ARGUMENTS$
|
||
* <pItem> es el puntero a la estructura item que ser examinada.
|
||
* El item pasado puede ser de cualquier tipo de datos, aunque
|
||
* arrays de objetos y bloques de c¢digos son bloqueados
|
||
* solamente. Otros tipos de datos no necesitan bloqueo as¡
|
||
* que ellos son simplemente ignorados.
|
||
* $RETURNS$
|
||
* Nada.
|
||
* $DESCRIPTION$
|
||
* El recolector de memoria usa la funci¢n hb_gcItemRef() durante la
|
||
* inspecci¢n de punteros de memoria referenciados.
|
||
* Esta funci¢n chequea el tipo del item pasado y examina recursivamente
|
||
* todos los otros bloques de memoria referenciados por este item, si
|
||
* ‚ste es un array un objeto ¢ un bloque de c¢digo
|
||
*
|
||
* NOTA: Esta funci¢n es reservada para el recolector de memoria (RM)
|
||
* solamente. Esta NO debe ser llamada desde el c¢digo del usuario
|
||
* llamarla puede causar resultados impredecibles (bloques de
|
||
* memoria referenciados por el item pasado pueden ser liberados
|
||
* prematuramente durante la recoleci¢n de memoria m s cercana).
|
||
* $STATUS$
|
||
* C
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
|
||
* $END$
|
||
*/
|
||
|
||
/* $DOC$
|
||
* $FUNCNAME$
|
||
* HB_GCALL()
|
||
* $CATEGORY$
|
||
* Colector de memoria
|
||
* $ONELINER$
|
||
* Inspecciona la memoria y libera los bloques de memoria sin uso
|
||
* $SYNTAX$
|
||
* HB_GCALL()
|
||
* $ARGUMENTS$
|
||
* Ninguno
|
||
* $RETURNS$
|
||
* NIL
|
||
* $DESCRIPTION$
|
||
* Esta funci¢n libera todos los bloques de memoria que son considerados
|
||
* como "basura".
|
||
* $STATUS$
|
||
* Harbour
|
||
* $COMPLIANCE$
|
||
* Esta funci¢n es una extensi¢n de Harbour.
|
||
* $PLATFORMS$
|
||
* Todas
|
||
* $FILES$
|
||
* Archivo fuente: ../source/vm/garbage.c
|
||
* $SEEALSO$
|
||
* hb_gcCollectAll()
|
||
* $END$
|
||
*/
|
||
|
||
|