]> git.llucax.com Git - software/dgc/naive.git/blob - alloc.d
19aceaa1888bddee3e56b0ac5d385c267220e9a5
[software/dgc/naive.git] / alloc.d
1 /**
2  * This module contains a minimal garbage collector implementation according to
3  * Tango requirements.  This library is mostly intended to serve as an example,
4  * but it is usable in applications which do not rely on a garbage collector
5  * to clean up memory (ie. when dynamic array resizing is not used, and all
6  * memory allocated with 'new' is freed deterministically with 'delete').
7  *
8  * Please note that block attribute data must be tracked, or at a minimum, the
9  * FINALIZE bit must be tracked for any allocated memory block because calling
10  * rt_finalize on a non-object block can result in an access violation.  In the
11  * allocator below, this tracking is done via a leading uint bitmask.  A real
12  * allocator may do better to store this data separately, similar to the basic
13  * GC normally used by Tango.
14  *
15  * Copyright: Public Domain
16  * License:   BOLA
17  * Authors:   Leandro Lucarella
18  */
19
20 module alloc;
21
22 version (Win32)
23 {
24     private import tango.sys.win32.UserGdi;
25 }
26 else version (Posix)
27 {
28     private import tango.stdc.posix.sys.mman;
29     private import tango.stdc.stdlib;
30 }
31 else
32 {
33     private import tango.stdc.stdlib;
34 }
35
36 static if (is(typeof(VirtualAlloc)))
37 {
38
39     void* mem_alloc(size_t size)
40     {
41         return VirtualAlloc(null, size, MEM_RESERVE, PAGE_READWRITE);
42     }
43
44     /**
45      * Free memory allocated with alloc().
46      * Returns:
47      *      0       success
48      *      !=0     failure
49      */
50     int mem_free(void* ptr, size_t size)
51     {
52         return cast(int)(VirtualFree(ptr, 0, MEM_RELEASE) == 0);
53     }
54
55 }
56 else static if (is(typeof(mmap)))
57 {
58
59     void* mem_alloc(size_t size)
60     {
61         void* ptr = mmap(null, size, PROT_READ | PROT_WRITE,
62                             MAP_PRIVATE | MAP_ANON, -1, 0);
63         if (ptr == MAP_FAILED)
64            ptr = null;
65         return ptr;
66     }
67
68     int mem_free(void* ptr, size_t size)
69     {
70         return munmap(ptr, size);
71     }
72
73 }
74 else static if (is(typeof(valloc)))
75 {
76
77     void* mem_alloc(size_t size)
78     {
79         return valloc(size);
80     }
81
82     int mem_free(void* ptr, size_t size)
83     {
84         free(ptr);
85         return 0;
86     }
87 }
88 else static if (is(typeof(malloc)))
89 {
90
91     // NOTE: This assumes malloc granularity is at least size_t.sizeof.  If
92     //       (req_size + PAGESIZE) is allocated, and the pointer is rounded up
93     //       to PAGESIZE alignment, there will be space for a void* at the end
94     //       after PAGESIZE bytes used by the GC.
95
96
97     enum { PAGESIZE = 4096 }
98
99     const size_t PAGE_MASK = PAGESIZE - 1;
100
101     void* mem_alloc(size_t size)
102     {
103         byte* p, q;
104         p = cast(byte *) malloc(size + PAGESIZE);
105         q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
106         * cast(void**)(q + size) = p;
107         return q;
108     }
109
110     int mem_free(void* ptr, size_t size)
111     {
112         free(*cast(void**)(cast(byte*) ptr + size));
113         return 0;
114     }
115
116 }
117 else
118 {
119
120     static assert(false, "No supported allocation methods available.");
121
122 }
123
124 // vim: set et sw=4 sts=4 :