| 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; } }+/ |