@@ -71,6 +71,12 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
7171
7272 static if (is (Allocator == RCIAllocator) || is (Allocator == RCISharedAllocator))
7373 {
74+ static if (is (Allocator == RCISharedAllocator))
75+ {
76+ shared bool nullParent = true ;
77+ shared bool nullParentWait = true ;
78+ }
79+
7480 @nogc nothrow pure @safe
7581 Allocator parent ()
7682 {
@@ -104,9 +110,22 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
104110 }
105111 else
106112 {
107- auto fn = (() @trusted =>
108- cast (RCIAllocator function () @nogc nothrow pure @safe )(&wrapProcAllocatorObject))();
109- _parent = fn();
113+ import core.atomic : cas, atomicLoad, atomicStore;
114+
115+ if ((() @trusted => cas(&nullParent, true , false ))())
116+ {
117+ auto fn = (() @trusted =>
118+ cast (RCISharedAllocator function () @nogc nothrow pure @safe )
119+ (&wrapProcAllocatorObject))();
120+ _parent = fn();
121+ // Notify other threads that the parent has been set
122+ atomicStore(nullParentWait, false );
123+ }
124+ else
125+ {
126+ // Busy-wait for the parent to be set
127+ while (atomicLoad(nullParentWait)) {}
128+ }
110129 }
111130 }
112131
@@ -600,3 +619,10 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
600619 assert (a.parent.bytesUsed == 100 + uint .sizeof);
601620 assert ((() nothrow @nogc => a.deallocate(b))());
602621}
622+
623+ @system unittest
624+ {
625+ import std.experimental.allocator : RCISharedAllocator;
626+
627+ AffixAllocator! (RCISharedAllocator, size_t ) a;
628+ }
0 commit comments