/*
 * $Id: garbage.txt,v 1.8 2001/03/16 15:01:20 rglab Exp $
*/

/*  $DOC$
 *  $FUNCNAME$
 *      The Garbage Collector
 *  $CATEGORY$
 *      Document
 *  $ONELINER$
 *      Readme for Harbour Garbage Collect Feature
 *  $DESCRIPTION$
 *      The garbage collector uses the following logic:
 *      - first collect all memory allocations that can cause garbage;
 *      - next scan all variables if these memory blocks are still referenced.
 *
 *      Notice that only arrays, objects and codeblocks are collected because
 *      these are the only datatypes that can cause self-references (a[1]:=a)
 *      or circular references (a[1]:=b; b[1]:=c; c[1]:=a) that cannot be
 *      properly deallocated by simple reference counting.
 *
 *      Since all variables in harbour are stored inside some available tables
 *      (the eval stack, memvars table and array of static variables) then checking
 *      if the reference is still alive is quite easy and doesn't require any
 *      special treatment during memory allocation. Additionaly the garbage
 *      collector is scanning some internal data used by harbour objects
 *      implementation that also stores some values that can contain memory
 *      references. These data are used to initialize class instance variables
 *      and are stored in class shared variables.
 *
 *      In special cases when the value of a harbour variable is stored internally
 *      in some static area (at C or assembler level), the garbage collector will
 *      be not able to scan such values since it doesn't know their location. This 
 *      could cause some memory blocks to be released prematurely. To prevent the 
 *      premature deallocation of such memory blocks the static data have to store
 *      a pointer to the value created with hb_itemNew() function.
 *      Example:
 *        static HB_ITEM s_item; // this item can be released by the GC 
 *
 *        static HB_ITEM_PTR pItem; // this item will be maintained correctly
 *        pItem = hb_itemNew( hb_param(1, IT_BLOCK) ); 
 *
 *      However, scanning of all variables can be a time consuming operation. It
 *      requires that all allocated arrays have to be traversed through all their
 *      elements to find more arrays. Also all codeblocks are scanned for detached
 *      local variables they are referencing. For this reason, looking for unreferenced
 *      memory blocks is performed during the idle states.
 *
 *      The idle state is a state when there is no real application code
 *      executed. For example, the user code is stopped for 0.1 of a second
 *      during INKEY(0.1) - Harbour is checking the keyboard only
 *      during this time. It leaves however quite enough time for
 *      many other background tasks. One such background task can be looking
 *      for unreferenced memory blocks.
 *
 *      Allocating memory    </par>
 *      -----------------
 *
 *      The garbage collector collects memory blocks allocated with hb_gcAlloc()
 *      function calls. Memory allocated by hb_gcAlloc() should be released with
 *      hb_gcFree() function.
 *
 *      The garbage collecting   </par>
 *      ----------------------
 *
 *      During scanning of unreferenced memory the GC is using a mark & sweep
 *      algorithm. This is done in three steps:
 *
 *      1) mark all memory blocks allocated by the GC with unused flag;
 *
 *      2) sweep (scan) all known places and clear unused flag for memory
 *      blocks that are referenced there;
 *
 *      3) finalize collecting by deallocation of all memory blocks that are
 *      still marked as unused and that are not locked.
 *
 *      To speed things up, the mark step is simplified by swapping the meaning
 *      of the unused flag. After deallocation of unused blocks all still alive
 *      memory blocks are marked with the same 'used' flag so we can reverse
 *      the meaning of this flag to 'unused' state in the next collecting.
 *      All new or unlocked memory blocks are automatically marked as 'unused'
 *      using the current flag, which assures that all memory blocks are marked
 *      with the same flag before the sweep step will start.
 *      See hb_gcCollectAll()  and hb_gcItemRef()
 *
 *      Calling the garbage collector from harbour code   </par>
 *      -----------------------------------------------
 *
 *      The garbage collector can be called directly from the harbour code.
 *      This is usefull in situations where there is no idle states available
 *      or the application is working in the loop with no user interaction
 *      and there is many memory allocations.
 *      See HB_GCALL() for explanation of how to call this function from your
 *      harbour code.
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcFree(),hb_gcCollectAll(),hb_gcItemRef(),HB_GCALL(),HB_IDLESTATE()
 *  $END$
 */

/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcAlloc()
 *  $CATEGORY$
 *      The garbage collector
 *  $ONELINER$
 *      Allocates memory that will be collected by the garbage collector.
 *  $SYNTAX$
 *      #include <hbapi.h>
 *      void *hb_gcAlloc( ULONG ulSize,
 *      HB_GARBAGE_FUNC_PTR pCleanupFunc );
 *  $ARGUMENTS$
 *      <ulSize> Requested size of memory block
 *
 *      <pCleanupFunc> Pointer to HB_GARBAGE_FUNC function that will be called
 *      directly before releasing the garbage memory block or NULL. This
 *      function should release all other memory allocated and stored inside
 *      the memory block. For example, it releases all items stored inside
 *      the array. The functions receives a single parameter: the pointer
 *      to memory allocated by hb_gcAlloc().
 *  $RETURNS$
 *      The pointer to allocated memory or it generates an internal
 *      unrecoverable error.
 *  $DESCRIPTION$
 *      hb_gcAlloc() is used to allocate the memory that will be tracked
 *      by the garbage collector. It allows to properly release memory
 *      in case of self-referencing or cross-referencing harbour level
 *      variables.
 *      Memory allocated with this function should be released with
 *      hb_gcFree() function or it will be automatically deallocated
 *      by the GC if it is not locked or if it is not referenced by some
 *      harbour level variable.
 *  $EXAMPLES$
 *      See source/vm/arrays.c
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      This function is a Harbour extension
 *  $PLATFORMS$
 *      All
 *  $FILES$
 *      source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcFree()
 *  $END$
 */

/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcFree()
 *  $CATEGORY$
 *      The garbage collector
 *  $ONELINER$
 *      Releases the memory that was allocated with hb_gcAlloc().
 *  $SYNTAX$
 *      void hb_gcFree( void *pMemoryPtr );
 *  $ARGUMENTS$
 *      <pMemoryPtr> The pointer to memory for release. This memory
 *        pointer have to be allocated with hb_gcAlloc() function.
 *  $RETURNS$
 *      Nothing.
 *  $DESCRIPTION$
 *      hb_gcFree() is used to deallocate the memory that was
 *      allocated with the hb_gcAlloc() function.
 *  $EXAMPLES$
 *      See source/vm/arrays.c
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      This function is a Harbour extension
 *  $PLATFORMS$
 *      All
 *  $FILES$
 *      source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc()
 *  $END$
 */

/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcCollectAll()
 *  $CATEGORY$
 *      The garbage collector
 *  $ONELINER$
 *      Scans all memory blocks and releases the garbage memory.
 *  $SYNTAX$
 *      void hb_gcCollectAll( void );
 *  $ARGUMENTS$
 *      None.
 *  $RETURNS$
 *      Nothing.
 *  $DESCRIPTION$
 *      This function scans the eval stack, the memvars table, the array
 *      of static variables and table of created classes for referenced
 *      memory blocks. After scanning all unused memory blocks and blocks
 *      that are not locked are released.
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      This function is a Harbour extension
 *  $PLATFORMS$
 *      All
 *  $FILES$
 *      source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcFree()
 *  $END$
 */

/*  $DOC$
 *  $FUNCNAME$
 *      hb_gcItemRef()
 *  $CATEGORY$
 *      The garbage collector
 *  $ONELINER$
 *      Marks the memory to prevent deallocation by the garbage collector.
 *  $SYNTAX$
 *      void hb_gcItemRef( HB_ITEM_PTR pItem );
 *  $ARGUMENTS$
 *      <pItem>  The pointer to item structure that will be scanned. The
 *      passed item can be of any datatype although arrays, objects
 *      and codeblocks are scanned only. Other datatypes don't require
 *      locking so they are simply ignored.
 *  $RETURNS$
 *      Nothing.
 *  $DESCRIPTION$
 *      The garbage collector uses hb_gcItemRef() function during
 *      scanning of referenced memory pointers. This function checks the
 *      type of passed item and scans recursively all other memory blocks
 *      referenced by this item if it is an array, an object or a codeblock.
 *
 *      NOTE: This function is reserved for the garbage collector only. It
 *            cannot be called from the user code - calling it can cause
 *            unpredicted results (memory blocks referenced by the
 *            passed item can be released prematurely during the closest
 *            garbage collection).
 *  $STATUS$
 *      C
 *  $COMPLIANCE$
 *      This function is a Harbour extension
 *  $PLATFORMS$
 *      All
 *  $FILES$
 *      source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcAlloc(),hb_gcFree()
 *  $END$
 */

/*  $DOC$
 *  $FUNCNAME$
 *      HB_GCALL()
 *  $CATEGORY$
 *      The garbage collector
 *  $ONELINER$
 *      Scans the memory and releases all garbage memory blocks.
 *  $SYNTAX$
 *      HB_GCALL()
 *  $ARGUMENTS$
 *      None
 *  $RETURNS$
 *      NIL
 *  $DESCRIPTION$
 *      This function releases all memory blocks that are considered
 *      as the garbage.
 *  $STATUS$
 *      Harbour
 *  $COMPLIANCE$
 *      This function is a Harbour extension
 *  $PLATFORMS$
 *      All
 *  $FILES$
 *      source/vm/garbage.c
 *  $SEEALSO$
 *      hb_gcCollectAll()
 *  $END$
 */
