/* * $Id$ */ /* $DOC$ * $TEMPLATE$ * Document * $NAME$ * 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 PHB_ITEM 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 * ----------------- * * 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 * ---------------------- * * 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 * ----------------------------------------------- * * 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$ * $TEMPLATE$ * Function * $NAME$ * hb_gcAlloc() * $CATEGORY$ * API * $SUBCATEGORY$ * Garbage Collector * $ONELINER$ * Allocates memory that will be collected by the garbage collector. * $SYNTAX$ * #include "hbapi.h" * void * hb_gcAlloc( HB_SIZE nSize, * HB_GARBAGE_FUNC_PTR pCleanupFunc ); * $ARGUMENTS$ * Requested size of memory block * * 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 src/vm/arrays.c * $STATUS$ * C * $COMPLIANCE$ * H * $PLATFORMS$ * All * $FILES$ * src/vm/garbage.c * $SEEALSO$ * hb_gcFree() * $END$ */ /* $DOC$ * $TEMPLATE$ * Function * $NAME$ * hb_gcFree() * $CATEGORY$ * API * $SUBCATEGORY$ * Garbage Collector * $ONELINER$ * Releases the memory that was allocated with hb_gcAlloc(). * $SYNTAX$ * void hb_gcFree( void *pMemoryPtr ); * $ARGUMENTS$ * 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 src/vm/arrays.c * $STATUS$ * C * $COMPLIANCE$ * H * $PLATFORMS$ * All * $FILES$ * src/vm/garbage.c * $SEEALSO$ * hb_gcAlloc() * $END$ */ /* $DOC$ * $TEMPLATE$ * Function * $NAME$ * hb_gcCollectAll() * $CATEGORY$ * API * $SUBCATEGORY$ * 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$ * H * $PLATFORMS$ * All * $FILES$ * src/vm/garbage.c * $SEEALSO$ * hb_gcAlloc(),hb_gcFree() * $END$ */ /* $DOC$ * $TEMPLATE$ * Function * $NAME$ * hb_gcItemRef() * $CATEGORY$ * API * $SUBCATEGORY$ * Garbage Collector * $ONELINER$ * Marks the memory to prevent deallocation by the garbage collector. * $SYNTAX$ * void hb_gcItemRef( PHB_ITEM pItem ); * $ARGUMENTS$ * 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$ * H * $PLATFORMS$ * All * $FILES$ * src/vm/garbage.c * $SEEALSO$ * hb_gcAlloc(),hb_gcFree() * $END$ */ /* $DOC$ * $TEMPLATE$ * Procedure * $NAME$ * HB_GCALL() * $CATEGORY$ * API * $SUBCATEGORY$ * Garbage Collector * $ONELINER$ * Scans the memory and releases all garbage memory blocks. * $SYNTAX$ * HB_GCALL() * $ARGUMENTS$ * None * $DESCRIPTION$ * This function releases all memory blocks that are considered * as the garbage. * $STATUS$ * Harbour * $COMPLIANCE$ * H * $PLATFORMS$ * All * $FILES$ * src/vm/garbage.c * $SEEALSO$ * hb_gcCollectAll() * $END$ */