/*
 * $Id: garbage.txt,v 1.1.1.1 2001/12/21 10:49:26 ronpinkas Exp $
 */

/*
 * Las siguientes partes son derechos adquiridos de sus autores individuales.
 * www - http://www.harbour-project.org
 *
 * Copyright 2000 Alejandro de Grate <alex_degarate@hotmail.com>
 * Documentacin en Espaol de:
 *         Readme, hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(),
 *         hb_gcUnlockItem(), hb_gcCollectAll(), hb_gcItemRef(), HB_GCALL()
 *
 * Copyright 2000 brian Brian Hays <bhays@abacuslaw.com>
 * Documentacin en Ingls de:
 *         Readme, hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(),
 *         hb_gcUnlockItem(), hb_gcCollectAll(), hb_gcItemRef(), HB_GCALL()
 *
 * Vea doc/license.txt por los trminos de la licencia.
 *
 */


/*  $DOC$
 *  $FUNCNAME$
 *      Recolector de memoria
 *  $CATEGORY$
 *      Documentacin - Recolector de memoria
 *  $ONELINER$
 *      Lame con las caractersticas de la recoleccion de memoria en Harbour.
 *  $DESCRIPTION$
 *      El recolector de memoria (garbage collector) usa la siguiente lgica:
 *      - primero recolectar todas las ubicaciones de memoria que puedan
 *        constituirse en "basura"
 *      - luego inspeccionar todas las variables, por si esos bloques estn
 *        todava referenciados.
 *
 *      Note que slo arrays, objetos y bloques de cdigo 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
 *      estticas), entonces chequear si la referencia es todava activa es
 *      bastante fcil y no requiere ningn tratamiento especial durante la
 *      la asignacin de memoria. Adicionalmente el recolector de memoria
 *      inspecciona algunos datos internos usados por la implementacin de
 *      objetos de Harbour que tambin 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 algn area esttica (a nivel de lenguaje C
 *       asembler), por ejemplo SETKEY() almacena bloques de cdigo que
 *      sern evaluados caundo se presione una tecla, el recolector de
 *      memoria no ser capaz de inspecionar esos valores porque este no
 *      conoce su ubicacin. Esto podra ocasionar que algunos bloques de
 *      memoria sean liberados prematuramente. Para prevenir la prematura
 *      desasignacin 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/sin uso  */
 *
 *      El bloque de memoria puede ser bloqueado con hb_gcLockItem(), mtodo
 *      recomendado si un tem de estructura es usado  la funcin hb_gcLock()
 *      un puntero directo a memoria es usado.
 *      El bloque de memoria puede ser desbloqueado por hb_gcUnlockItem() 
 *      hb_gcUnlock().
 *
 *      Ntese sin embargo que todas las variables pasadas a una funcin de
 *      bajo nivel son pasadas mediante la pila de evaluacin (eval stack),
 *      as ellas no necesitan bloquearse durante la llamada a la funcin.
 *      El bloque puede ser requerido, si un valor pasado es copiado dentro
 *      de algn area esttica para hacerla disponible para otras funciones
 *      de bajo nivel, llamadas despus de la salida de la funcin que
 *      almacena el valor. Esto es requerido porque el valor es removido de
 *      la pila de evaluacin despus de la llamada a la funcin y esta no
 *      puede seguir siendo referenciada por otras variables.
 *
 *      Sin embargo la inspeccin de todas las variables puede ser una
 *      operacin de un gran consumo de tiempo. Esto requiere que todos los
 *      arrays asignados tengan que ser recorridos a travs de todos sus
 *      elementos para encontrar ms arrays.
 *      Tambin todos los bloques de cdigo son inspecionados, en busca de
 *      variables locales separadas que ellos estan referenciando. Por esta
 *      esta razn, la busqueda por bloques de memoria no referenciados es
 *      realizada durante los estados inactivos.
 *
 *      El estado inactivo es el estado cuando no hay un cdigo real de la
 *      aplicacin ejecutndose. Por ejemplo, el cdigo del usuario es
 *      detenido durante 0.1 segundo por INKEY(0.1) - Harbour esta chequeando
 *      slo 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 bsqueda de bloques de memoria no
 *      referenciados.
 *
 *      Asignando memoria </par>
 *      -----------------
 *
 *      El recolector de memoria, recoge bloques de memoria asignados con
 *      llamadas a la funcin hb_gcAlloc().   La memoria asignada por
 *      hb_gcAlloc() debera ser liberada con la funcin hb_gcFree().
 *
 *
 *      Bloqueando memoria  </par>
 *      ------------------
 *
 *      La memoria asignada con hb_gcAlloc() debera ser bloqueada para
 *      prevenir una automtica liberacin 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
 *      estticas de lenguaje C deben ser bloqueadas.
 *      Vea hb_gcLockItem() y hb_gcUnlockItem() para ms informacin.
 *
 *
 *      La recolecin de memoria  </par>
 *      ------------------------
 *
 *      Durante la bsqueda 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 desasignacin de todos los bloques de
 *      memoria que an estan marcados como sin uso y que no estn bloqueados.
 *
 *      Para acelerar las cosas un poco, la etapa de marca es simplificada
 *      por la inversin del significado de la bandera "sin uso". Despus de
 *      la desasignacin de los bloques sin uso, todos los bloques todava
 *      activos son marcados con la bandera "usado" as nosotros podemos
 *      invertir el significado de esta bandera al estado "sin uso" en la
 *      prxima recolecin
 *      Todos los bloques de memoria nuevos  sin bloquear son automticamente
 *      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 cdigo Harbour  </par>
 *      ------------------------------------------------------
 *
 *      El RM puede ser llamado directamente desde un programa en Harbour.
 *      Esto es til en situaciones donde no hay estados inactivos disponibles
 *       la aplicacin esta trabajando en un bucle sin interaccin con el
 *      usuario y hay muchas asignaciones de memoria.
 *      Vea HB_GCALL() por una explicacin de como llamar a esta funcin
 *      desde el cdigo 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$
 *      Recolector 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 tamao solicitado del bloque de memoria.
 *
 *      <pCleanupFunc> es un Puntero a la funcin HB_GARBAGE_FUNC que ser
 *      llamada directamente antes de la liberacin del bloque de memoria
 *      sin uso  NULL. Esta funcin debera liberar toda otra memoria
 *      asignada y almacenada dentro del bloque de memoria.
 *      Por ejemplo, esta libera todos los items almacenados dentro del array.
 *      La funcin recibe un slo parmetro: 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 liberacin de memoria en el caso
 *      de variables auto-referenciadas  con referencias cruzadas a nivel de
 *      Harbour.
 *      La memoria asignada con esta funcin debera ser liberada con la
 *      funcin hb_gcFree()  esta ser automticamente 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 funcin es una extensin de Harbour.
 *  $PLATFORMS$
 *      Todas
 *  $FILES$
 *      Archivo fuente: ../source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
 *  $END$
 */


/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcFree()
 *  $CATEGORY$
 *      Recolector 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 funcin hb_gcAlloc().
 *  $RETURNS$
 *      Nada.
 *  $DESCRIPTION$
 *      La funcin hb_gcFree() es usada para liberar la memoria que fu
 *      asignada con la funcin hb_gcAlloc().
 *  $EXAMPLES$
 *      Vea ../source/vm/arrays.c
 *      hb_gcFree( (void *) pBaseArray );  // puntero al array a liberar
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      Esta funcin es una extensin de Harbour.
 *  $PLATFORMS$
 *      Todas
 *  $FILES$
 *      Archivo fuente: ../source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcLockItem(),hb_gcUnlockItem()
 *  $END$
 */


/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcLockItem()
 *  $CATEGORY$
 *      Recolector de memoria
 *  $ONELINER$
 *      Bloquea la memoria para prevenir la desasignacin 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
 *      objetos y bloques de cdigos son bloqueados solamente. Otros tipos de
 *      datos no necesitan bloqueo as que ellos son simplemente ignorados.
 *  $RETURNS$
 *      Nada.
 *  $DESCRIPTION$
 *      La funcin hb_gcLockItem() es usada para bloquear el puntero de memoria
 *      almacenado en la estructura item pasada. Este suprime la liberacin
 *      de memoria si el RM no encuentra alguna referencia a este puntero
 *      El RM almacena un contador de bloqueo y cada llamada a esta funcin
 *      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 liberacin por el RM
 *      hb_gcLockItem( sk_list_tmp-> pAction );
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      Esta funcin es una extensin de Harbour.
 *  $PLATFORMS$
 *      Todas
 *  $FILES$
 *      Archivo fuente: ../source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcFree(),hb_gcUnlockItem()
 *  $END$
 */


/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcUnlockItem()
 *  $CATEGORY$
 *      Recolector de memoria
 *  $ONELINER$
 *      Desbloquea la memmoria para prevenir la liberacin 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
 *      objetos y bloques de cdigos son bloqueados solamente. Otros tipos de
 *      datos no necesitan bloqueo as que ellos son simplemente ignorados.
 *  $RETURNS$
 *      Nada.
 *  $DESCRIPTION$
 *      La funcin 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 recoleccin 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 funcin decrementa el contador.
 *      Esta funcin no libera la memoria almacenada dentro del item, la
 *      memoria debe ser desasignada sin embargo durante la recolecin de
 *      memoria sin uso ms 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 funcin es una extensin de Harbour.
 *  $PLATFORMS$
 *      Todas
 *  $FILES$
 *      Archivo fuente: ../source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcFree(),hb_gcLockItem()
 *  $END$
 */


/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcCollectAll()
 *  $CATEGORY$
 *      Recolector 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 funcin examina la pila de evaluacin, las tablas de memvars,
 *      el array de variables estticas y las tablas de clases creadas en
 *      busca de bloques de memoria referenciados. Despus de examinar todos
 *      los bloques de memoria sin uso y los bloques que no estan bloqueados,
 *      son liberados.
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      Esta funcin es una extensin 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$
 *      Recolector de memoria
 *  $ONELINER$
 *      Marca la memoria para prevenir la desasignacin 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
 *      objetos y bloques de cdigos 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 funcin hb_gcItemRef() durante la
 *      inspeccin de punteros de memoria referenciados. Esta funcin 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 cdigo
 *
 *      NOTA: Esta funcin es reservada para el recolector de memoria (RM)
 *            solamente. Esta NO debe ser llamada desde el cdigo del usuario
 *            llamarla puede causar resultados impredecibles (bloques de
 *            memoria referenciados por el item pasado pueden ser liberados
 *            prematuramente durante la recolecin de memoria ms cercana).
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      Esta funcin es una extensin 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$
 *      Recolector de memoria
 *  $ONELINER$
 *      Inspeciona la memoria y libera todos los bloques de memoria sin uso.
 *  $SYNTAX$
 *      HB_GCALL()
 *  $ARGUMENTS$
 *      Ninguno
 *  $RETURNS$
 *      NIL
 *  $DESCRIPTION$
 *      Esta funcin libera todos los bloques de memoria que son considerados
 *      como "basura".
 *  $STATUS$
 *      Harbour
 *  $COMPLIANCE$
 *      Esta funcin es una extensin de Harbour.
 *  $PLATFORMS$
 *      Todas
 *  $FILES$
 *      Archivo fuente: ../source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcCollectAll()
 *  $END$
 */
