xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
18  * Authors:   Sean Kelly
19  */
20 module core.internal.gc.impl.manual.gc;
21 
22 import core.gc.gcinterface;
23 
24 import core.internal.container.array;
25 
26 import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
27 static import core.memory;
28 
29 extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
30 
31 // register GC in C constructor (_STI_)
pragma(crt_constructor)32 extern(C) pragma(crt_constructor) void _d_register_manual_gc()
33 {
34     import core.gc.registry;
35     registerGCFactory("manual", &initialize);
36 }
37 
initialize()38 private GC initialize()
39 {
40     import core.lifetime : emplace;
41 
42     auto gc = cast(ManualGC) cstdlib.malloc(__traits(classInstanceSize, ManualGC));
43     if (!gc)
44         onOutOfMemoryError();
45 
46     return emplace(gc);
47 }
48 
49 class ManualGC : GC
50 {
51     Array!Root roots;
52     Array!Range ranges;
53 
this()54     this()
55     {
56     }
57 
~this()58     ~this()
59     {
60         // TODO: cannot free as memory is overwritten and
61         //  the monitor is still read in rt_finalize (called by destroy)
62         // cstdlib.free(cast(void*) this);
63     }
64 
enable()65     void enable()
66     {
67     }
68 
disable()69     void disable()
70     {
71     }
72 
collect()73     void collect() nothrow
74     {
75     }
76 
collectNoStack()77     void collectNoStack() nothrow
78     {
79     }
80 
minimize()81     void minimize() nothrow
82     {
83     }
84 
getAttr(void * p)85     uint getAttr(void* p) nothrow
86     {
87         return 0;
88     }
89 
setAttr(void * p,uint mask)90     uint setAttr(void* p, uint mask) nothrow
91     {
92         return 0;
93     }
94 
clrAttr(void * p,uint mask)95     uint clrAttr(void* p, uint mask) nothrow
96     {
97         return 0;
98     }
99 
malloc(size_t size,uint bits,const TypeInfo ti)100     void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
101     {
102         void* p = cstdlib.malloc(size);
103 
104         if (size && p is null)
105             onOutOfMemoryError();
106         return p;
107     }
108 
qalloc(size_t size,uint bits,const scope TypeInfo ti)109     BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
110     {
111         BlkInfo retval;
112         retval.base = malloc(size, bits, ti);
113         retval.size = size;
114         retval.attr = bits;
115         return retval;
116     }
117 
calloc(size_t size,uint bits,const TypeInfo ti)118     void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
119     {
120         void* p = cstdlib.calloc(1, size);
121 
122         if (size && p is null)
123             onOutOfMemoryError();
124         return p;
125     }
126 
realloc(void * p,size_t size,uint bits,const TypeInfo ti)127     void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
128     {
129         p = cstdlib.realloc(p, size);
130 
131         if (size && p is null)
132             onOutOfMemoryError();
133         return p;
134     }
135 
extend(void * p,size_t minsize,size_t maxsize,const TypeInfo ti)136     size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow
137     {
138         return 0;
139     }
140 
reserve(size_t size)141     size_t reserve(size_t size) nothrow
142     {
143         return 0;
144     }
145 
free(void * p)146     void free(void* p) nothrow @nogc
147     {
148         cstdlib.free(p);
149     }
150 
151     /**
152      * Determine the base address of the block containing p.  If p is not a gc
153      * allocated pointer, return null.
154      */
addrOf(void * p)155     void* addrOf(void* p) nothrow @nogc
156     {
157         return null;
158     }
159 
160     /**
161      * Determine the allocated size of pointer p.  If p is an interior pointer
162      * or not a gc allocated pointer, return 0.
163      */
sizeOf(void * p)164     size_t sizeOf(void* p) nothrow @nogc
165     {
166         return 0;
167     }
168 
169     /**
170      * Determine the base address of the block containing p.  If p is not a gc
171      * allocated pointer, return null.
172      */
query(void * p)173     BlkInfo query(void* p) nothrow
174     {
175         return BlkInfo.init;
176     }
177 
stats()178     core.memory.GC.Stats stats() nothrow
179     {
180         return typeof(return).init;
181     }
182 
profileStats()183     core.memory.GC.ProfileStats profileStats() nothrow
184     {
185         return typeof(return).init;
186     }
187 
addRoot(void * p)188     void addRoot(void* p) nothrow @nogc
189     {
190         roots.insertBack(Root(p));
191     }
192 
removeRoot(void * p)193     void removeRoot(void* p) nothrow @nogc
194     {
195         foreach (ref r; roots)
196         {
197             if (r is p)
198             {
199                 r = roots.back;
200                 roots.popBack();
201                 return;
202             }
203         }
204         assert(false);
205     }
206 
207     @property RootIterator rootIter() return @nogc
208     {
209         return &rootsApply;
210     }
211 
212     private int rootsApply(scope int delegate(ref Root) nothrow dg)
213     {
214         foreach (ref r; roots)
215         {
216             if (auto result = dg(r))
217                 return result;
218         }
219         return 0;
220     }
221 
222     void addRange(void* p, size_t sz, const TypeInfo ti = null) nothrow @nogc
223     {
224         ranges.insertBack(Range(p, p + sz, cast() ti));
225     }
226 
227     void removeRange(void* p) nothrow @nogc
228     {
229         foreach (ref r; ranges)
230         {
231             if (r.pbot is p)
232             {
233                 r = ranges.back;
234                 ranges.popBack();
235                 return;
236             }
237         }
238         assert(false);
239     }
240 
241     @property RangeIterator rangeIter() return @nogc
242     {
243         return &rangesApply;
244     }
245 
246     private int rangesApply(scope int delegate(ref Range) nothrow dg)
247     {
248         foreach (ref r; ranges)
249         {
250             if (auto result = dg(r))
251                 return result;
252         }
253         return 0;
254     }
255 
256     void runFinalizers(const scope void[] segment) nothrow
257     {
258     }
259 
260     bool inFinalizer() nothrow
261     {
262         return false;
263     }
264 
265     ulong allocatedInCurrentThread() nothrow
266     {
267         return typeof(return).init;
268     }
269 }
270