1 /**
2  * Contains a registry for GC factories.
3  *
4  * Copyright: Copyright Digital Mars 2016.
5  * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6  * Authors:   Martin Nowak
7  */
8 module core.gc.registry;
9 
10 import core.gc.gcinterface : GC;
11 
12 /*@nogc nothrow:*/
13 
14 /**
15  * A factory function that instantiates an implementation of the GC interface.
16  * In case the instance was allocated on the C heap, it is supposed to
17  * free itself upon calling it's destructor.
18  *
19  * The factory should print an error and abort the program if it
20  * cannot successfully initialize the GC instance.
21  */
22 alias GCFactory = GC function();
23 
24 /**
25  * Register a GC factory under the given `name`.  This function must be called
26  * from a C constructor before druntime is initialized.
27  *
28  * To use the registered GC, it's name must be specified gcopt runtime option,
29  * e.g. by passing $(TT, --DRT-gcopt=gc:my_gc_name) as application argument.
30  *
31  * Params:
32  *   name = name of the GC implementation; should be unique
33  *   factory = function to instantiate the implementation
34  * Note: The registry does not perform synchronization, as registration is
35  *   assumed to be executed serially, as is the case for C constructors.
36  * See_Also:
37  *   $(LINK2 https://dlang.org/spec/garbage.html#gc_config, Configuring the Garbage Collector)
38  */
39 void registerGCFactory(string name, GCFactory factory) nothrow @nogc
40 {
41     import core.stdc.stdlib : realloc;
42 
43     auto ptr = cast(Entry*)realloc(entries.ptr, (entries.length + 1) * Entry.sizeof);
44     entries = ptr[0 .. entries.length + 1];
45     entries[$ - 1] = Entry(name, factory);
46 }
47 
48 /**
49  * Called during runtime initialization to initialize a GC instance of given `name`.
50  *
51  * Params:
52  *   name = name of the GC to instantiate
53  * Returns:
54  *   The created GC instance or `null` if no factory for that name was registered
55  */
56 GC createGCInstance(string name)
57 {
58     import core.stdc.stdlib : free;
59 
60     foreach (entry; entries)
61     {
62         if (entry.name != name)
63             continue;
64         auto instance = entry.factory();
65         // only one GC at a time for now, so free the registry to not leak
66         free(entries.ptr);
67         entries = null;
68         return instance;
69     }
70     return null;
71 }
72 
73 // list of all registerd GCs
74 const(Entry[]) registeredGCFactories(scope int dummy=0) nothrow @nogc
75 {
76     return entries;
77 }
78 
79 private:
80 
81 struct Entry
82 {
83     string name;
84     GCFactory factory;
85 }
86 
87 __gshared Entry[] entries;