xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/gc/impl/manual/gc.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /**
2  * This module contains a minimal garbage collector implementation according to
3  * published requirements.  This library is mostly intended to serve as an
4  * example, but it is usable in applications which do not rely on a garbage
5  * collector to clean up memory (ie. when dynamic array resizing is not used,
6  * and all memory allocated with 'new' is freed deterministically with
7  * 'delete').
8  *
9  * Please note that block attribute data must be tracked, or at a minimum, the
10  * FINALIZE bit must be tracked for any allocated memory block because calling
11  * rt_finalize on a non-object block can result in an access violation.  In the
12  * allocator below, this tracking is done via a leading uint bitmask.  A real
13  * allocator may do better to store this data separately, similar to the basic
14  * GC.
15  *
16  * Copyright: Copyright Sean Kelly 2005 - 2016.
17  * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
18  * Authors:   Sean Kelly
19  */
20 
21 /*          Copyright Sean Kelly 2005 - 2016.
22  * Distributed under the Boost Software License, Version 1.0.
23  *    (See accompanying file LICENSE or copy at
24  *          http://www.boost.org/LICENSE_1_0.txt)
25  */
26 module gc.impl.manual.gc;
27 
28 import gc.config;
29 import gc.gcinterface;
30 
31 import rt.util.container.array;
32 
33 import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
34 static import core.memory;
35 
36 extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
37 
38 class ManualGC : GC
39 {
40     __gshared Array!Root roots;
41     __gshared Array!Range ranges;
42 
initialize(ref GC gc)43     static void initialize(ref GC gc)
44     {
45         import core.stdc.string;
46 
47         if (config.gc != "manual")
48             return;
49 
50         auto p = cstdlib.malloc(__traits(classInstanceSize, ManualGC));
51         if (!p)
52             onOutOfMemoryError();
53 
54         auto init = typeid(ManualGC).initializer();
55         assert(init.length == __traits(classInstanceSize, ManualGC));
56         auto instance = cast(ManualGC) memcpy(p, init.ptr, init.length);
57         instance.__ctor();
58 
59         gc = instance;
60     }
61 
finalize(ref GC gc)62     static void finalize(ref GC gc)
63     {
64         if (config.gc != "manual")
65             return;
66 
67         auto instance = cast(ManualGC) gc;
68         instance.Dtor();
69         cstdlib.free(cast(void*) instance);
70     }
71 
this()72     this()
73     {
74     }
75 
Dtor()76     void Dtor()
77     {
78     }
79 
enable()80     void enable()
81     {
82     }
83 
disable()84     void disable()
85     {
86     }
87 
collect()88     void collect() nothrow
89     {
90     }
91 
collectNoStack()92     void collectNoStack() nothrow
93     {
94     }
95 
minimize()96     void minimize() nothrow
97     {
98     }
99 
getAttr(void * p)100     uint getAttr(void* p) nothrow
101     {
102         return 0;
103     }
104 
setAttr(void * p,uint mask)105     uint setAttr(void* p, uint mask) nothrow
106     {
107         return 0;
108     }
109 
clrAttr(void * p,uint mask)110     uint clrAttr(void* p, uint mask) nothrow
111     {
112         return 0;
113     }
114 
malloc(size_t size,uint bits,const TypeInfo ti)115     void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
116     {
117         void* p = cstdlib.malloc(size);
118 
119         if (size && p is null)
120             onOutOfMemoryError();
121         return p;
122     }
123 
qalloc(size_t size,uint bits,const TypeInfo ti)124     BlkInfo qalloc(size_t size, uint bits, const TypeInfo ti) nothrow
125     {
126         BlkInfo retval;
127         retval.base = malloc(size, bits, ti);
128         retval.size = size;
129         retval.attr = bits;
130         return retval;
131     }
132 
calloc(size_t size,uint bits,const TypeInfo ti)133     void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
134     {
135         void* p = cstdlib.calloc(1, size);
136 
137         if (size && p is null)
138             onOutOfMemoryError();
139         return p;
140     }
141 
realloc(void * p,size_t size,uint bits,const TypeInfo ti)142     void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
143     {
144         p = cstdlib.realloc(p, size);
145 
146         if (size && p is null)
147             onOutOfMemoryError();
148         return p;
149     }
150 
extend(void * p,size_t minsize,size_t maxsize,const TypeInfo ti)151     size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow
152     {
153         return 0;
154     }
155 
reserve(size_t size)156     size_t reserve(size_t size) nothrow
157     {
158         return 0;
159     }
160 
free(void * p)161     void free(void* p) nothrow
162     {
163         cstdlib.free(p);
164     }
165 
166     /**
167      * Determine the base address of the block containing p.  If p is not a gc
168      * allocated pointer, return null.
169      */
addrOf(void * p)170     void* addrOf(void* p) nothrow
171     {
172         return null;
173     }
174 
175     /**
176      * Determine the allocated size of pointer p.  If p is an interior pointer
177      * or not a gc allocated pointer, return 0.
178      */
sizeOf(void * p)179     size_t sizeOf(void* p) nothrow
180     {
181         return 0;
182     }
183 
184     /**
185      * Determine the base address of the block containing p.  If p is not a gc
186      * allocated pointer, return null.
187      */
query(void * p)188     BlkInfo query(void* p) nothrow
189     {
190         return BlkInfo.init;
191     }
192 
stats()193     core.memory.GC.Stats stats() nothrow
194     {
195         return typeof(return).init;
196     }
197 
addRoot(void * p)198     void addRoot(void* p) nothrow @nogc
199     {
200         roots.insertBack(Root(p));
201     }
202 
removeRoot(void * p)203     void removeRoot(void* p) nothrow @nogc
204     {
205         foreach (ref r; roots)
206         {
207             if (r is p)
208             {
209                 r = roots.back;
210                 roots.popBack();
211                 return;
212             }
213         }
214         assert(false);
215     }
216 
217     @property RootIterator rootIter() return @nogc
218     {
219         return &rootsApply;
220     }
221 
222     private int rootsApply(scope int delegate(ref Root) nothrow dg)
223     {
224         foreach (ref r; roots)
225         {
226             if (auto result = dg(r))
227                 return result;
228         }
229         return 0;
230     }
231 
232     void addRange(void* p, size_t sz, const TypeInfo ti = null) nothrow @nogc
233     {
234         ranges.insertBack(Range(p, p + sz, cast() ti));
235     }
236 
237     void removeRange(void* p) nothrow @nogc
238     {
239         foreach (ref r; ranges)
240         {
241             if (r.pbot is p)
242             {
243                 r = ranges.back;
244                 ranges.popBack();
245                 return;
246             }
247         }
248         assert(false);
249     }
250 
251     @property RangeIterator rangeIter() return @nogc
252     {
253         return &rangesApply;
254     }
255 
256     private int rangesApply(scope int delegate(ref Range) nothrow dg)
257     {
258         foreach (ref r; ranges)
259         {
260             if (auto result = dg(r))
261                 return result;
262         }
263         return 0;
264     }
265 
266     void runFinalizers(in void[] segment) nothrow
267     {
268     }
269 
270     bool inFinalizer() nothrow
271     {
272         return false;
273     }
274 }
275