88module core.gc.registry ;
99
1010import core.gc.gcinterface : GC ;
11+ import core.thread.threadbase : ThreadBase;
1112
1213/* @nogc nothrow:*/
1314
@@ -21,28 +22,49 @@ import core.gc.gcinterface : GC;
2122 */
2223alias GCFactory = GC function ();
2324
25+ /**
26+ * A function that will initialize a thread before the GC has been initialized.
27+ * Once the GC is initialized, the interface method GC.initThread for each new
28+ * thread.
29+ */
30+ alias GCThreadInitFunction = void function (ThreadBase base) nothrow @nogc ;
31+
2432/**
2533 * Register a GC factory under the given `name`. This function must be called
2634 * from a C constructor before druntime is initialized.
2735 *
2836 * To use the registered GC, it's name must be specified gcopt runtime option,
2937 * e.g. by passing $(TT, --DRT-gcopt=gc:my_gc_name) as application argument.
3038 *
39+ * The thread init function will be called *only before* the GC has been
40+ * initialized to the registered GC. It is called as the first step in starting
41+ * the new thread before the thread is registered with the runtime as a running
42+ * thread. This allows any specific thread data that is needed for running the
43+ * GC to be registered with the thread object.
44+ *
45+ * After the GC is initialized, the GC interface function `initThread` is
46+ * called instead. This function should expect the possibility that the
47+ * reciprocal `cleanupThread` method may not be called if the GC is never
48+ * initialized.
49+ *
3150 * Params:
3251 * name = name of the GC implementation; should be unique
3352 * factory = function to instantiate the implementation
53+ * threadInit = function to call from a new thread *before* registration in
54+ * the list of running threads, to set up any GC-specific data.
3455 * Note: The registry does not perform synchronization, as registration is
3556 * assumed to be executed serially, as is the case for C constructors.
3657 * See_Also:
3758 * $(LINK2 https://dlang.org/spec/garbage.html#gc_config, Configuring the Garbage Collector)
3859 */
39- void registerGCFactory (string name, GCFactory factory) nothrow @nogc
60+ void registerGCFactory (string name, GCFactory factory,
61+ GCThreadInitFunction threadInit = null ) nothrow @nogc
4062{
4163 import core.stdc.stdlib : realloc;
4264
4365 auto ptr = cast (Entry* )realloc(entries.ptr, (entries.length + 1 ) * Entry.sizeof);
4466 entries = ptr[0 .. entries.length + 1 ];
45- entries[$ - 1 ] = Entry(name, factory);
67+ entries[$ - 1 ] = Entry(name, factory, threadInit );
4668}
4769
4870/**
@@ -70,6 +92,22 @@ GC createGCInstance(string name)
7092 return null ;
7193}
7294
95+ /**
96+ * Get the thread init function used for the selected GC.
97+ *
98+ * Note, this must be called before `createGCInstance`. It is typically called by
99+ * `rt_init`.
100+ */
101+ GCThreadInitFunction threadInit (string name) nothrow @nogc
102+ {
103+ foreach (entry; entries)
104+ {
105+ if (entry.name == name)
106+ return entry.threadInit;
107+ }
108+ return null ;
109+ }
110+
73111// list of all registerd GCs
74112const (Entry[]) registeredGCFactories (scope int dummy=0 ) nothrow @nogc
75113{
@@ -82,6 +120,7 @@ struct Entry
82120{
83121 string name;
84122 GCFactory factory;
123+ GCThreadInitFunction threadInit;
85124}
86125
87126__gshared Entry[] entries;
0 commit comments