/* * $Id$ */ /* * Las siguientes partes son derechos adquiridos de sus autores individuales. * www - http://www.harbour-project.org * * Copyright 2000 Alejandro de G rate * 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 * 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 * ----------------- * * 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 * ------------------ * * 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 * ------------------------ * * 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 * void *hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc ); * $ARGUMENTS$ * es el tama¤o solicitado del bloque de memoria. * * 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$ * 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$ * 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$ * 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$ * 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$ */