1 /**
2  * The memory module provides an interface to the garbage collector and to
3  * any other OS or API-level memory management facilities.
4  *
5  * Copyright: Copyright (C) 2005-2006 Sean Kelly.  All rights reserved.
6  * License:   BSD style: $(LICENSE)
7  * Authors:   Sean Kelly
8  */
9 module tango.core.Memory;
10 
11 public import core.memory;
12 
13 /+private
14 {
15     extern (C) void gc_init();
16     extern (C) void gc_term();
17 
18     extern (C) void gc_enable();
19     extern (C) void gc_disable();
20     extern (C) void gc_collect();
21     extern (C) void gc_minimize();
22 
23     extern (C) uint gc_getAttr( void* p );
24     extern (C) uint gc_setAttr( void* p, uint a );
25     extern (C) uint gc_clrAttr( void* p, uint a );
26 
27     extern (C) void*  gc_malloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
28     extern (C) void*  gc_calloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
29     extern (C) void*  gc_realloc( void* p, size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
30     extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
31     extern (C) size_t gc_reserve( size_t sz );
32     extern (C) void   gc_free( void* p );
33 
34     extern (C) void*   gc_addrOf( void* p );
35     extern (C) size_t  gc_sizeOf( void* p );
36 
37     struct BlkInfo_
38     {
39         void*  base;
40         size_t size;
41         uint   attr;
42     }
43 
44     extern (C) BlkInfo_ gc_query( void* p );
45 
46     extern (C) void gc_addRoot( void* p );
47     extern (C) void gc_addRange( void* p, size_t sz );
48 
49     extern (C) void gc_removeRoot( void* p );
50     extern (C) void gc_removeRange( void* p );
51 
52     extern(C) Object gc_weakpointerGet(void* wp);
53     extern(C) void*  gc_weakpointerCreate(Object r);
54     extern(C) void   gc_weakpointerDestroy(void* wp);
55 
56     alias extern(D) void delegate() ddel;
57     alias extern(D) void delegate(int, int) dint;
58 
59     extern (C) void gc_monitor(ddel begin, dint end );
60 }
61 
62 
63 /**
64  * This struct encapsulates all garbage collection functionality for the D
65  * programming language.
66  *
67  * Documentation of runtime configuration:
68  *
69  * The environment variable D_PRECISE_HEAP can be used to control the behavior
70  * of the GC at runtime.
71  *  D_PRECISE_HEAP=1 enable precise scanning
72  *  D_PRECISE_HEAP=0 disable precise scanning (may save space because no bitmasks need to be stored)
73  */
74 struct GC
75 {
76     /**
77      * Enables the garbage collector if collections have previously been
78      * suspended by a call to disable.  This function is reentrant, and
79      * must be called once for every call to disable before the garbage
80      * collector is enabled.
81      */
82     static void enable()
83     {
84         gc_enable();
85     }
86 
87 
88     /**
89      * Disables the garbage collector.  This function is reentrant, but
90      * enable must be called once for each call to disable.
91      */
92     static void disable()
93     {
94         gc_disable();
95     }
96 
97 
98     /**
99      * Begins a full collection.  While the meaning of this may change based
100      * on the garbage collector implementation, typical behavior is to scan
101      * all stack segments for roots, mark accessible memory blocks as alive,
102      * and then to reclaim free space.  This action may need to suspend all
103      * running threads for at least part of the collection process.
104      */
105     static void collect()
106     {
107         gc_collect();
108     }
109 
110     /**
111      * Indicates that the managed memory space be minimized by returning free
112      * physical memory to the operating system.  The amount of free memory
113      * returned depends on the allocator design and on program behavior.
114      */
115     static void minimize()
116     {
117         gc_minimize();
118     }
119 
120 
121     /**
122      * Elements for a bit field representing memory block attributes.  These
123      * are manipulated via the getAttr, setAttr, clrAttr functions.
124      */
125     enum BlkAttr : uint
126     {
127         FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
128         NO_SCAN  = 0b0000_0010, /// Do not scan through this block on collect.
129         NO_MOVE  = 0b0000_0100  /// Do not move this memory block on collect.
130     }
131 
132 
133     /**
134      * Contains aggregate information about a block of managed memory.  The
135      * purpose of this struct is to support a more efficient query style in
136      * instances where detailed information is needed.
137      *
138      * base = A pointer to the base of the block in question.
139      * size = The size of the block, calculated from base.
140      * attr = Attribute bits set on the memory block.
141      */
142     alias BlkInfo_ BlkInfo;
143 
144 
145     /**
146      * Returns a bit field representing all block attributes set for the memory
147      * referenced by p.  If p references memory not originally allocated by this
148      * garbage collector, points to the interior of a memory block, or if p is
149      * null, zero will be returned.
150      *
151      * Params:
152      *  p = A pointer to the root of a valid memory block or to null.
153      *
154      * Returns:
155      *  A bit field containing any bits set for the memory block referenced by
156      *  p or zero on error.
157      */
158     static uint getAttr( void* p )
159     {
160         return gc_getAttr( p );
161     }
162 
163 
164     /**
165      * Sets the specified bits for the memory references by p.  If p references
166      * memory not originally allocated by this garbage collector, points to the
167      * interior of a memory block, or if p is null, no action will be performed.
168      *
169      * Params:
170      *  p = A pointer to the root of a valid memory block or to null.
171      *  a = A bit field containing any bits to set for this memory block.
172      *
173      *  The result of a call to getAttr after the specified bits have been
174      *  set.
175      */
176     static uint setAttr( void* p, uint a )
177     {
178         return gc_setAttr( p, a );
179     }
180 
181 
182     /**
183      * Clears the specified bits for the memory references by p.  If p
184      * references memory not originally allocated by this garbage collector,
185      * points to the interior of a memory block, or if p is null, no action
186      * will be performed.
187      *
188      * Params:
189      *  p = A pointer to the root of a valid memory block or to null.
190      *  a = A bit field containing any bits to clear for this memory block.
191      *
192      * Returns:
193      *  The result of a call to getAttr after the specified bits have been
194      *  cleared.
195      */
196     static uint clrAttr( void* p, uint a )
197     {
198         return gc_clrAttr( p, a );
199     }
200 
201 
202     /**
203      * Requests an aligned block of managed memory from the garbage collector.
204      * This memory may be deleted at will with a call to free, or it may be
205      * discarded and cleaned up automatically during a collection run.  If
206      * allocation fails, this function will call onOutOfMemory which is
207      * expected to throw an OutOfMemoryException.
208      *
209      * Params:
210      *  sz = The desired allocation size in bytes.
211      *  ba = A bitmask of the attributes to set on this block.
212      *  bitMask = The pointer offset information for precise heap scanning.
213      *
214      * Returns:
215      *  A reference to the allocated memory or null if insufficient memory
216      *  is available.
217      *
218      * Throws:
219      *  OutOfMemoryException on allocation failure.
220      */
221     static void* malloc( size_t sz, uint ba = 0,
222         PointerMap bitMask = PointerMap.init )
223     {
224         return gc_malloc( sz, ba, bitMask );
225     }
226 
227 
228     /**
229      * Requests an aligned block of managed memory from the garbage collector,
230      * which is initialized with all bits set to zero.  This memory may be
231      * deleted at will with a call to free, or it may be discarded and cleaned
232      * up automatically during a collection run.  If allocation fails, this
233      * function will call onOutOfMemory which is expected to throw an
234      * OutOfMemoryException.
235      *
236      * Params:
237      *  sz = The desired allocation size in bytes.
238      *  ba = A bitmask of the attributes to set on this block.
239      *  bitMask = The pointer offset information for precise heap scanning.
240      *
241      * Returns:
242      *  A reference to the allocated memory or null if insufficient memory
243      *  is available.
244      *
245      * Throws:
246      *  OutOfMemoryException on allocation failure.
247      */
248     static void* calloc( size_t sz, uint ba = 0,
249         PointerMap bitMask = PointerMap.init )
250     {
251         return gc_calloc( sz, ba, bitMask );
252     }
253 
254 
255     /**
256      * If sz is zero, the memory referenced by p will be deallocated as if
257      * by a call to free.  A new memory block of size sz will then be
258      * allocated as if by a call to malloc, or the implementation may instead
259      * resize the memory block in place.  The contents of the new memory block
260      * will be the same as the contents of the old memory block, up to the
261      * lesser of the new and old sizes.  Note that existing memory will only
262      * be freed by realloc if sz is equal to zero.  The garbage collector is
263      * otherwise expected to later reclaim the memory block if it is unused.
264      * If allocation fails, this function will call onOutOfMemory which is
265      * expected to throw an OutOfMemoryException.  If p references memory not
266      * originally allocated by this garbage collector, or if it points to the
267      * interior of a memory block, no action will be taken.  If ba is zero
268      * (the default) and p references the head of a valid, known memory block
269      * then any bits set on the current block will be set on the new block if a
270      * reallocation is required.  If ba is not zero and p references the head
271      * of a valid, known memory block then the bits in ba will replace those on
272      * the current memory block and will also be set on the new block if a
273      * reallocation is required.  Similarly, if bitMask is non-null, then
274      * the bitmask for the current block will propagated to the new block.
275      * Otherwise, the bitmask provided will be propagated to the old block.
276      *
277      * Params:
278      *  p  = A pointer to the root of a valid memory block or to null.
279      *  sz = The desired allocation size in bytes.
280      *  ba = A bitmask of the attributes to set on this block.
281      *  bitMask = The pointer offset information for precise heap scanning.
282      *
283      * Returns:
284      *  A reference to the allocated memory on success or null if sz is
285      *  zero.  On failure, the original value of p is returned.
286      *
287      * Throws:
288      *  OutOfMemoryException on allocation failure.
289      */
290     static void* realloc( void* p, size_t sz, uint ba = 0,
291         PointerMap bitMask = PointerMap.init )
292     {
293         return gc_realloc( p, sz, ba, bitMask );
294     }
295 
296 
297     /**
298      * Requests that the managed memory block referenced by p be extended in
299      * place by at least mx bytes, with a desired extension of sz bytes.  If an
300      * extension of the required size is not possible, if p references memory
301      * not originally allocated by this garbage collector, or if p points to
302      * the interior of a memory block, no action will be taken.
303      *
304      * Params:
305      *  mx = The minimum extension size in bytes.
306      *  sz = The  desired extension size in bytes.
307      *
308      * Returns:
309      *  The size in bytes of the extended memory block referenced by p or zero
310      *  if no extension occurred.
311      */
312     static size_t extend( void* p, size_t mx, size_t sz )
313     {
314         return gc_extend( p, mx, sz );
315     }
316 
317 
318     /**
319      * Requests that at least sz bytes of memory be obtained from the operating
320      * system and marked as free.
321      *
322      * Params:
323      *  sz = The desired size in bytes.
324      *
325      * Returns:
326      *  The actual number of bytes reserved or zero on error.
327      */
328     static size_t reserve( size_t sz )
329     {
330         return gc_reserve( sz );
331     }
332 
333 
334     /**
335      * Deallocates the memory referenced by p.  If p is null, no action
336      * occurs.  If p references memory not originally allocated by this
337      * garbage collector, or if it points to the interior of a memory block,
338      * no action will be taken.  The block will not be finalized regardless
339      * of whether the FINALIZE attribute is set.  If finalization is desired,
340      * use delete instead.
341      *
342      * Params:
343      *  p = A pointer to the root of a valid memory block or to null.
344      */
345     static void free( void* p )
346     {
347         gc_free( p );
348     }
349 
350 
351     /**
352      * Returns the base address of the memory block containing p.  This value
353      * is useful to determine whether p is an interior pointer, and the result
354      * may be passed to routines such as sizeOf which may otherwise fail.  If p
355      * references memory not originally allocated by this garbage collector, if
356      * p is null, or if the garbage collector does not support this operation,
357      * null will be returned.
358      *
359      * Params:
360      *  p = A pointer to the root or the interior of a valid memory block or to
361      *      null.
362      *
363      * Returns:
364      *  The base address of the memory block referenced by p or null on error.
365      */
366     static void* addrOf( void* p )
367     {
368         return gc_addrOf( p );
369     }
370 
371 
372     /**
373      * Returns the true size of the memory block referenced by p.  This value
374      * represents the maximum number of bytes for which a call to realloc may
375      * resize the existing block in place.  If p references memory not
376      * originally allocated by this garbage collector, points to the interior
377      * of a memory block, or if p is null, zero will be returned.
378      *
379      * Params:
380      *  p = A pointer to the root of a valid memory block or to null.
381      *
382      * Returns:
383      *  The size in bytes of the memory block referenced by p or zero on error.
384      */
385     static size_t sizeOf( void* p )
386     {
387         return gc_sizeOf( p );
388     }
389 
390 
391     /**
392      * Returns aggregate information about the memory block containing p.  If p
393      * references memory not originally allocated by this garbage collector, if
394      * p is null, or if the garbage collector does not support this operation,
395      * BlkInfo.init will be returned.  Typically, support for this operation
396      * is dependent on support for addrOf.
397      *
398      * Params:
399      *  p = A pointer to the root or the interior of a valid memory block or to
400      *      null.
401      *
402      * Returns:
403      *  Information regarding the memory block referenced by p or BlkInfo.init
404      *  on error.
405      */
406     static BlkInfo query( void* p )
407     {
408         return gc_query( p );
409     }
410 
411 
412     /**
413      * Adds the memory address referenced by p to an internal list of roots to
414      * be scanned during a collection.  If p is null, no operation is
415      * performed.
416      *
417      * Params:
418      *  p = A pointer to a valid memory address or to null.
419      */
420     static void addRoot( void* p )
421     {
422         gc_addRoot( p );
423     }
424 
425 
426     /**
427      * Adds the memory block referenced by p and of size sz to an internal list
428      * of ranges to be scanned during a collection.  If p is null, no operation
429      * is performed.
430      *
431      * Params:
432      *  p  = A pointer to a valid memory address or to null.
433      *  sz = The size in bytes of the block to add.  If sz is zero then the
434      *       no operation will occur.  If p is null then sz must be zero.
435      */
436     static void addRange( void* p, size_t sz )
437     {
438         gc_addRange( p, sz );
439     }
440 
441 
442     /**
443      * Removes the memory block referenced by p from an internal list of roots
444      * to be scanned during a collection.  If p is null or does not represent
445      * a value previously passed to add(void*) then no operation is performed.
446      *
447      *  p  = A pointer to a valid memory address or to null.
448      */
449     static void removeRoot( void* p )
450     {
451         gc_removeRoot( p );
452     }
453 
454 
455     /**
456      * Removes the memory block referenced by p from an internal list of ranges
457      * to be scanned during a collection.  If p is null or does not represent
458      * a value previously passed to add(void*, size_t) then no operation is
459      * performed.
460      *
461      * Params:
462      *  p  = A pointer to a valid memory address or to null.
463      */
464     static void removeRange( void* p )
465     {
466         gc_removeRange( p );
467     }
468     
469     /**
470      * Removes the memory block referenced by p from an internal list of ranges
471      * to be scanned during a collection.  If p is null or does not represent
472      * a value previously passed to add(void*, size_t) then no operation is
473      * performed.
474      *
475      * Params:
476      *  p  = A pointer to a valid memory address or to null.
477      */
478     static void monitor( void delegate() begin, void delegate(int, int) end )
479     {
480         gc_monitor( begin, end );
481     }
482     
483 
484     /**
485      * Create a weak pointer to the given object.
486      * Returns a pointer to an opaque struct allocated in C memory.
487      */
488     static void* weakPointerCreate( Object o )
489     {
490         return gc_weakpointerCreate (o);
491     }
492 
493 
494     /**
495      * Destroy a weak pointer returned by weakpointerCreate().
496      * If null is passed, nothing happens.
497      */
498     static void weakPointerDestroy( void* p )
499     {
500         return gc_weakpointerDestroy (p);
501     }
502 
503 
504     /**
505      * Query a weak pointer and return either the object passed to
506      * weakpointerCreate, or null if it was free'd in the meantime.
507      * If null is passed, null is returned.
508      */
509     static Object weakPointerGet( void* p )
510     {
511         return gc_weakpointerGet (p);
512     }
513 
514 
515     /**
516     * Returns the amount to allocate to keep some extra space
517     * for large allocations the extra allocated space decreases, but is still enough
518     * so that the number of reallocations when linearly growing stays logaritmic
519     * Params:
520     * newlength = the number of elements to allocate
521     * elSize = size of one element
522     */
523     static size_t growLength (size_t newlength, size_t elSize=1)
524     {   
525         return growLength (newlength, elSize, 100, 0, 1);
526     }
527     
528 
529     /**
530     * Returns the amount to allocate to keep some extra space
531     * for large allocations the extra allocated space decreases, but is still enough
532     * so that the number of reallocations when linearly growing stays logaritmic
533     * Params:
534     * newlength = the number of elements to allocate
535     * elSize = size of one element
536     * a = maximum extra space in percent (the allocated space gets rounded up, so might be larger)
537     * b = flatness factor, how fast the extra space decreases with array size (the larger the more constant)
538     * minBits = minimum number of bits of newlength
539     */
540     static size_t growLength (size_t newlength, size_t elSize, size_t a, size_t b=0, size_t minBits=1)
541     {
542         static size_t log2(size_t c)
543         {
544             // could use the bsr bit op
545             size_t i=1;
546             while(c >>= 1)
547                   ++i;
548             return i;
549         }
550 
551         size_t newext = 0;
552         size_t newcap = newlength*elSize;
553         long mult = 100 + a*(minBits+b) / (log2(newlength)+b);
554         newext = elSize*cast(size_t)(((newcap * mult)+99) / 100);
555         newcap = newext > newcap ? newext : newcap; // just to handle overflows
556         return newcap;
557     }
558 }+/