123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
|
/**
* The memory module provides an interface to the garbage collector and to
* any other OS or API-level memory management facilities.
*
* Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved.
* License: BSD style: $(LICENSE)
* Authors: Sean Kelly
*/
module tango.core.Memory;
public import core.memory;
/+private
{
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void gc_enable();
extern (C) void gc_disable();
extern (C) void gc_collect();
extern (C) void gc_minimize();
extern (C) uint gc_getAttr( void* p );
extern (C) uint gc_setAttr( void* p, uint a );
extern (C) uint gc_clrAttr( void* p, uint a );
extern (C) void* gc_malloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
extern (C) void* gc_calloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
extern (C) size_t gc_reserve( size_t sz );
extern (C) void gc_free( void* p );
extern (C) void* gc_addrOf( void* p );
extern (C) size_t gc_sizeOf( void* p );
struct BlkInfo_
{
void* base;
size_t size;
uint attr;
}
extern (C) BlkInfo_ gc_query( void* p );
extern (C) void gc_addRoot( void* p );
extern (C) void gc_addRange( void* p, size_t sz );
extern (C) void gc_removeRoot( void* p );
extern (C) void gc_removeRange( void* p );
extern(C) Object gc_weakpointerGet(void* wp);
extern(C) void* gc_weakpointerCreate(Object r);
extern(C) void gc_weakpointerDestroy(void* wp);
alias extern(D) void delegate() ddel;
alias extern(D) void delegate(int, int) dint;
extern (C) void gc_monitor(ddel begin, dint end );
}
/**
* This struct encapsulates all garbage collection functionality for the D
* programming language.
*
* Documentation of runtime configuration:
*
* The environment variable D_PRECISE_HEAP can be used to control the behavior
* of the GC at runtime.
* D_PRECISE_HEAP=1 enable precise scanning
* D_PRECISE_HEAP=0 disable precise scanning (may save space because no bitmasks need to be stored)
*/
struct GC
{
/**
* Enables the garbage collector if collections have previously been
* suspended by a call to disable. This function is reentrant, and
* must be called once for every call to disable before the garbage
* collector is enabled.
*/
static void enable()
{
gc_enable();
}
/**
* Disables the garbage collector. This function is reentrant, but
* enable must be called once for each call to disable.
*/
static void disable()
{
gc_disable();
}
/**
* Begins a full collection. While the meaning of this may change based
* on the garbage collector implementation, typical behavior is to scan
* all stack segments for roots, mark accessible memory blocks as alive,
* and then to reclaim free space. This action may need to suspend all
* running threads for at least part of the collection process.
*/
static void collect()
{
gc_collect();
}
/**
* Indicates that the managed memory space be minimized by returning free
* physical memory to the operating system. The amount of free memory
* returned depends on the allocator design and on program behavior.
*/
static void minimize()
{
gc_minimize();
}
/**
* Elements for a bit field representing memory block attributes. These
* are manipulated via the getAttr, setAttr, clrAttr functions.
*/
enum BlkAttr : uint
{
FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect.
NO_MOVE = 0b0000_0100 /// Do not move this memory block on collect.
}
/**
* Contains aggregate information about a block of managed memory. The
* purpose of this struct is to support a more efficient query style in
* instances where detailed information is needed.
*
* base = A pointer to the base of the block in question.
* size = The size of the block, calculated from base.
* attr = Attribute bits set on the memory block.
*/
alias BlkInfo_ BlkInfo;
/**
* Returns a bit field representing all block attributes set for the memory
* referenced by p. If p references memory not originally allocated by this
* garbage collector, points to the interior of a memory block, or if p is
* null, zero will be returned.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*
* Returns:
* A bit field containing any bits set for the memory block referenced by
* p or zero on error.
*/
static uint getAttr( void* p )
{
return gc_getAttr( p );
}
/**
* Sets the specified bits for the memory references by p. If p references
* memory not originally allocated by this garbage collector, points to the
* interior of a memory block, or if p is null, no action will be performed.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* a = A bit field containing any bits to set for this memory block.
*
* The result of a call to getAttr after the specified bits have been
* set.
*/
static uint setAttr( void* p, uint a )
{
return gc_setAttr( p, a );
}
/**
* Clears the specified bits for the memory references by p. If p
* references memory not originally allocated by this garbage collector,
* points to the interior of a memory block, or if p is null, no action
* will be performed.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* a = A bit field containing any bits to clear for this memory block.
*
* Returns:
* The result of a call to getAttr after the specified bits have been
* cleared.
*/
static uint clrAttr( void* p, uint a )
{
return gc_clrAttr( p, a );
}
/**
* Requests an aligned block of managed memory from the garbage collector.
* This memory may be deleted at will with a call to free, or it may be
* discarded and cleaned up automatically during a collection run. If
* allocation fails, this function will call onOutOfMemory which is
* expected to throw an OutOfMemoryException.
*
* Params:
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
* bitMask = The pointer offset information for precise heap scanning.
*
* Returns:
* A reference to the allocated memory or null if insufficient memory
* is available.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* malloc( size_t sz, uint ba = 0,
PointerMap bitMask = PointerMap.init )
{
return gc_malloc( sz, ba, bitMask );
}
/**
* Requests an aligned block of managed memory from the garbage collector,
* which is initialized with all bits set to zero. This memory may be
* deleted at will with a call to free, or it may be discarded and cleaned
* up automatically during a collection run. If allocation fails, this
* function will call onOutOfMemory which is expected to throw an
* OutOfMemoryException.
*
* Params:
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
* bitMask = The pointer offset information for precise heap scanning.
*
* Returns:
* A reference to the allocated memory or null if insufficient memory
* is available.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* calloc( size_t sz, uint ba = 0,
PointerMap bitMask = PointerMap.init )
{
return gc_calloc( sz, ba, bitMask );
}
/**
* If sz is zero, the memory referenced by p will be deallocated as if
* by a call to free. A new memory block of size sz will then be
* allocated as if by a call to malloc, or the implementation may instead
* resize the memory block in place. The contents of the new memory block
* will be the same as the contents of the old memory block, up to the
* lesser of the new and old sizes. Note that existing memory will only
* be freed by realloc if sz is equal to zero. The garbage collector is
* otherwise expected to later reclaim the memory block if it is unused.
* If allocation fails, this function will call onOutOfMemory which is
* expected to throw an OutOfMemoryException. If p references memory not
* originally allocated by this garbage collector, or if it points to the
* interior of a memory block, no action will be taken. If ba is zero
* (the default) and p references the head of a valid, known memory block
* then any bits set on the current block will be set on the new block if a
* reallocation is required. If ba is not zero and p references the head
* of a valid, known memory block then the bits in ba will replace those on
* the current memory block and will also be set on the new block if a
* reallocation is required. Similarly, if bitMask is non-null, then
* the bitmask for the current block will propagated to the new block.
* Otherwise, the bitmask provided will be propagated to the old block.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
* bitMask = The pointer offset information for precise heap scanning.
*
* Returns:
* A reference to the allocated memory on success or null if sz is
* zero. On failure, the original value of p is returned.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* realloc( void* p, size_t sz, uint ba = 0,
PointerMap bitMask = PointerMap.init )
{
return gc_realloc( p, sz, ba, bitMask );
}
/**
* Requests that the managed memory block referenced by p be extended in
* place by at least mx bytes, with a desired extension of sz bytes. If an
* extension of the required size is not possible, if p references memory
* not originally allocated by this garbage collector, or if p points to
* the interior of a memory block, no action will be taken.
*
* Params:
* mx = The minimum extension size in bytes.
* sz = The desired extension size in bytes.
*
* Returns:
* The size in bytes of the extended memory block referenced by p or zero
* if no extension occurred.
*/
static size_t extend( void* p, size_t mx, size_t sz )
{
return gc_extend( p, mx, sz );
}
/**
* Requests that at least sz bytes of memory be obtained from the operating
* system and marked as free.
*
* Params:
* sz = The desired size in bytes.
*
* Returns:
* The actual number of bytes reserved or zero on error.
*/
static size_t reserve( size_t sz )
{
return gc_reserve( sz );
}
/**
* Deallocates the memory referenced by p. If p is null, no action
* occurs. If p references memory not originally allocated by this
* garbage collector, or if it points to the interior of a memory block,
* no action will be taken. The block will not be finalized regardless
* of whether the FINALIZE attribute is set. If finalization is desired,
* use delete instead.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*/
static void free( void* p )
{
gc_free( p );
}
/**
* Returns the base address of the memory block containing p. This value
* is useful to determine whether p is an interior pointer, and the result
* may be passed to routines such as sizeOf which may otherwise fail. If p
* references memory not originally allocated by this garbage collector, if
* p is null, or if the garbage collector does not support this operation,
* null will be returned.
*
* Params:
* p = A pointer to the root or the interior of a valid memory block or to
* null.
*
* Returns:
* The base address of the memory block referenced by p or null on error.
*/
static void* addrOf( void* p )
{
return gc_addrOf( p );
}
/**
* Returns the true size of the memory block referenced by p. This value
* represents the maximum number of bytes for which a call to realloc may
* resize the existing block in place. If p references memory not
* originally allocated by this garbage collector, points to the interior
* of a memory block, or if p is null, zero will be returned.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*
* Returns:
* The size in bytes of the memory block referenced by p or zero on error.
*/
static size_t sizeOf( void* p )
{
return gc_sizeOf( p );
}
/**
* Returns aggregate information about the memory block containing p. If p
* references memory not originally allocated by this garbage collector, if
* p is null, or if the garbage collector does not support this operation,
* BlkInfo.init will be returned. Typically, support for this operation
* is dependent on support for addrOf.
*
* Params:
* p = A pointer to the root or the interior of a valid memory block or to
* null.
*
* Returns:
* Information regarding the memory block referenced by p or BlkInfo.init
* on error.
*/
static BlkInfo query( void* p )
{
return gc_query( p );
}
/**
* Adds the memory address referenced by p to an internal list of roots to
* be scanned during a collection. If p is null, no operation is
* performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
*/
static void addRoot( void* p )
{
gc_addRoot( p );
}
/**
* Adds the memory block referenced by p and of size sz to an internal list
* of ranges to be scanned during a collection. If p is null, no operation
* is performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
* sz = The size in bytes of the block to add. If sz is zero then the
* no operation will occur. If p is null then sz must be zero.
*/
static void addRange( void* p, size_t sz )
{
gc_addRange( p, sz );
}
/**
* Removes the memory block referenced by p from an internal list of roots
* to be scanned during a collection. If p is null or does not represent
* a value previously passed to add(void*) then no operation is performed.
*
* p = A pointer to a valid memory address or to null.
*/
static void removeRoot( void* p )
{
gc_removeRoot( p );
}
/**
* Removes the memory block referenced by p from an internal list of ranges
* to be scanned during a collection. If p is null or does not represent
* a value previously passed to add(void*, size_t) then no operation is
* performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
*/
static void removeRange( void* p )
{
gc_removeRange( p );
}
/**
* Removes the memory block referenced by p from an internal list of ranges
* to be scanned during a collection. If p is null or does not represent
* a value previously passed to add(void*, size_t) then no operation is
* performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
*/
static void monitor( void delegate() begin, void delegate(int, int) end )
{
gc_monitor( begin, end );
}
/**
* Create a weak pointer to the given object.
* Returns a pointer to an opaque struct allocated in C memory.
*/
static void* weakPointerCreate( Object o )
{
return gc_weakpointerCreate (o);
}
/**
* Destroy a weak pointer returned by weakpointerCreate().
* If null is passed, nothing happens.
*/
static void weakPointerDestroy( void* p )
{
return gc_weakpointerDestroy (p);
}
/**
* Query a weak pointer and return either the object passed to
* weakpointerCreate, or null if it was free'd in the meantime.
* If null is passed, null is returned.
*/
static Object weakPointerGet( void* p )
{
return gc_weakpointerGet (p);
}
/**
* Returns the amount to allocate to keep some extra space
* for large allocations the extra allocated space decreases, but is still enough
* so that the number of reallocations when linearly growing stays logaritmic
* Params:
* newlength = the number of elements to allocate
* elSize = size of one element
*/
static size_t growLength (size_t newlength, size_t elSize=1)
{
return growLength (newlength, elSize, 100, 0, 1);
}
/**
* Returns the amount to allocate to keep some extra space
* for large allocations the extra allocated space decreases, but is still enough
* so that the number of reallocations when linearly growing stays logaritmic
* Params:
* newlength = the number of elements to allocate
* elSize = size of one element
* a = maximum extra space in percent (the allocated space gets rounded up, so might be larger)
* b = flatness factor, how fast the extra space decreases with array size (the larger the more constant)
* minBits = minimum number of bits of newlength
*/
static size_t growLength (size_t newlength, size_t elSize, size_t a, size_t b=0, size_t minBits=1)
{
static size_t log2(size_t c)
{
// could use the bsr bit op
size_t i=1;
while(c >>= 1)
++i;
return i;
}
size_t newext = 0;
size_t newcap = newlength*elSize;
long mult = 100 + a*(minBits+b) / (log2(newlength)+b);
newext = elSize*cast(size_t)(((newcap * mult)+99) / 100);
newcap = newext > newcap ? newext : newcap; // just to handle overflows
return newcap;
}
}+/
|