* bin/commit.hb
* config/detect.mk
* config/detfun.mk
* config/detplat.mk
* config/dir.mk
* config/dirsh.mk
* config/global.mk
* config/globsh.mk
* config/instsh.mk
* config/lang.hb
* config/lang2po.hb
* config/po2lang.hb
* config/postinst.hb
* contrib/hbexpat/tests/tohash.prg
* contrib/hbformat/utils/hbformat.ini
* contrib/hbmisc/hbedit.prg
* contrib/hbmxml/tests/testmxml.prg
* contrib/hbnetio/utils/hbnetio/_console.prg
* contrib/hbnetio/utils/hbnetio/_winsvc.prg
* contrib/hbnetio/utils/hbnetio/hbnetio.prg
* contrib/hbnetio/utils/hbnetio/netiomgm.hb
* contrib/hbwin/tests/ole.prg
* contrib/hbwin/tests/oletst2.js
* contrib/hbwin/tests/oletst2.vbs
* contrib/hbxpp/doc/en/binnumx.txt
* contrib/hbxpp/doc/en/dbcmdx.txt
* contrib/xhb/htmutil.prg
* contrib/xhb/tfile.prg
* contrib/xhb/tframe.prg
* contrib/xhb/thtm.prg
* ChangeLog.txt
* debian/copyright
* doc/class_tp.txt
* doc/hdr_tpl.txt
* doc/xhb-diff.txt
* LICENSE.txt
* package/harbour-wce.spec.in
* package/harbour-win.spec.in
* package/harbour.spec
* package/mpkg_rpm_wce.sh
* package/mpkg_rpm_win.sh
* package/mpkg_rpm.sh
* package/mpkg_src.sh
* package/mpkg_ver.sh
* src/rtl/achoice.prg
* src/rtl/getsys53.prg
* src/rtl/tgetlist.prg
* src/rtl/tlabel.prg
* src/rtl/tmenusys.prg
* tests/hbdoc.prg
* tests/langmsg.prg
* tests/rto_get.prg
* tests/rto_tb.prg
+ doc/en/ati.txt
+ doc/en/dirdrive.txt
+ doc/en/hashfunc.txt
+ doc/en/hbtoken.txt
+ doc/en/left.txt
+ doc/en/proc.txt
+ doc/en/strtran.txt
+ doc/en/transfrm.txt
+ doc/en/typefile.txt
* doc/en/*
* more partial sync with 3.4 fork
282 lines
9.1 KiB
Plaintext
282 lines
9.1 KiB
Plaintext
/* $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. Additionally 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:
|
|
```c
|
|
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 useful 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,
|
|
PHB_GARBAGE_FUNC 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.
|
|
$STATUS$
|
|
R
|
|
$COMPLIANCE$
|
|
H
|
|
$PLATFORMS$
|
|
All
|
|
$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$
|
|
<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.
|
|
$STATUS$
|
|
R
|
|
$COMPLIANCE$
|
|
H
|
|
$PLATFORMS$
|
|
All
|
|
$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$
|
|
R
|
|
$COMPLIANCE$
|
|
H
|
|
$PLATFORMS$
|
|
All
|
|
$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$
|
|
<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$
|
|
R
|
|
$COMPLIANCE$
|
|
H
|
|
$PLATFORMS$
|
|
All
|
|
$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$
|
|
R
|
|
$COMPLIANCE$
|
|
H
|
|
$PLATFORMS$
|
|
All
|
|
$SEEALSO$
|
|
hb_gcCollectAll()
|
|
$END$
|
|
*/
|