Skip to content

Commit

Permalink
Safely set parent for shared objects
Browse files Browse the repository at this point in the history
  • Loading branch information
edi33416 committed Apr 25, 2018
1 parent b0188dd commit 5877da2
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions std/experimental/allocator/building_blocks/affix_allocator.d
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)

static if (is(Allocator == RCIAllocator) || is(Allocator == RCISharedAllocator))
{
static if (is(Allocator == RCISharedAllocator))
{
shared bool nullParent = true;
shared bool nullParentWait = true;
}

@nogc nothrow pure @safe
Allocator parent()
{
Expand Down Expand Up @@ -104,9 +110,22 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
}
else
{
auto fn = (() @trusted =>
cast(RCIAllocator function() @nogc nothrow pure @safe)(&wrapProcAllocatorObject))();
_parent = fn();
import core.atomic : cas, atomicLoad, atomicStore;

if ((() @trusted => cas(&nullParent, true, false))())
{
auto fn = (() @trusted =>
cast(RCISharedAllocator function() @nogc nothrow pure @safe)
(&wrapProcAllocatorObject))();
_parent = fn();
// Notify other threads that the parent has been set
atomicStore(nullParentWait, false);
}
else
{
// Busy-wait for the parent to be set
while(atomicLoad(nullParentWait)) {}
}
}
}

Expand Down Expand Up @@ -600,3 +619,10 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
assert(a.parent.bytesUsed == 100 + uint.sizeof);
assert((() nothrow @nogc => a.deallocate(b))());
}

@system unittest
{
import std.experimental.allocator : RCISharedAllocator;

AffixAllocator!(RCISharedAllocator, size_t) a;
}

0 comments on commit 5877da2

Please sign in to comment.