Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions std/experimental/allocator/building_blocks/affix_allocator.d
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
if (r != Ternary.yes || p1 is null)
return r;
p1 = p1[stateSize!Prefix .. $];
auto p2 = (p1.ptr + p1.length - stateSize!Suffix)
.alignDownTo(Suffix.alignof);
result = p1[0 .. p2 - p1.ptr];
auto p2 = (() @trusted => (&p1[0] + p1.length - stateSize!Suffix)
.alignDownTo(Suffix.alignof))();
result = p1[0 .. p2 - &p1[0]];
return Ternary.yes;
}

Expand Down Expand Up @@ -435,8 +435,8 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
static assert(is(typeof(&MyAllocator.instance.prefix(e)) == const(uint)*));

void[] p;
assert(MyAllocator.instance.resolveInternalPointer(null, p) == Ternary.no);
Ternary r = MyAllocator.instance.resolveInternalPointer(d.ptr, p);
assert((() nothrow @safe @nogc => MyAllocator.instance.resolveInternalPointer(null, p))() == Ternary.no);
assert((() nothrow @safe => MyAllocator.instance.resolveInternalPointer(&d[0], p))() == Ternary.yes);
assert(p.ptr is d.ptr && p.length >= d.length);
}

Expand Down
51 changes: 37 additions & 14 deletions std/experimental/allocator/building_blocks/bitmapped_block.d
Original file line number Diff line number Diff line change
Expand Up @@ -1016,22 +1016,24 @@ struct BitmappedBlockWithInternalPointers(
}

/// Ditto
nothrow @safe @nogc
Ternary resolveInternalPointer(const void* p, ref void[] result)
{
if (p < _heap._payload.ptr
|| p >= _heap._payload.ptr + _heap._payload.length)
if ((() @trusted => _heap._payload
&& (p < &_heap._payload[0]
|| p >= &_heap._payload[0] + _heap._payload.length))())
{
return Ternary.no;
}
// Find block start
auto block = (p - _heap._payload.ptr) / _heap.blockSize;
auto block = (() @trusted => (p - &_heap._payload[0]) / _heap.blockSize)();
if (block >= _allocStart.length) return Ternary.no;
// Within an allocation, must find the 1 just to the left of it
auto i = _allocStart.find1Backward(block);
if (i == i.max) return Ternary.no;
auto j = _allocStart.find1(i + 1);
result = _heap._payload.ptr[cast(size_t) (_heap.blockSize * i)
.. cast(size_t) (_heap.blockSize * j)];
result = (() @trusted => _heap._payload.ptr[cast(size_t) (_heap.blockSize * i)
.. cast(size_t) (_heap.blockSize * j)])();
return Ternary.yes;
}

Expand Down Expand Up @@ -1089,24 +1091,29 @@ struct BitmappedBlockWithInternalPointers(
assert(b.length == 123);

void[] p;
Ternary r = h.resolveInternalPointer(b.ptr + 17, p);
void* offset = &b[0] + 17;
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
assert(p.ptr is b.ptr);
assert(p.length >= b.length);
b = h.allocate(4096);

h.resolveInternalPointer(b.ptr, p);
offset = &b[0];
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
assert(p is b);

h.resolveInternalPointer(b.ptr + 11, p);
offset = &b[0] + 11;
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
assert(p is b);

void[] unchanged = p;
h.resolveInternalPointer(b.ptr - 40_970, p);
offset = &b[0] - 40_970;
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.no);
assert(p is unchanged);

assert(h.expand(b, 1));
assert(b.length == 4097);
h.resolveInternalPointer(b.ptr + 4096, p);
offset = &b[0] + 4096;
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
assert(p.ptr is b.ptr);
}

Expand All @@ -1120,6 +1127,7 @@ struct BitmappedBlockWithInternalPointers(
Returns the number of most significant ones before a zero can be found in $(D
x). If $(D x) contains no zeros (i.e. is equal to $(D ulong.max)), returns 64.
*/
pure nothrow @safe @nogc
private uint leadingOnes(ulong x)
{
uint result = 0;
Expand All @@ -1131,7 +1139,7 @@ private uint leadingOnes(ulong x)
return result;
}

@system unittest
@safe unittest
{
assert(leadingOnes(0) == 0);
assert(leadingOnes(~0UL) == 64);
Expand All @@ -1145,6 +1153,7 @@ private uint leadingOnes(ulong x)
/**
Finds a run of contiguous ones in $(D x) of length at least $(D n).
*/
pure nothrow @safe @nogc
private uint findContigOnes(ulong x, uint n)
{
while (n > 1)
Expand All @@ -1156,7 +1165,7 @@ private uint findContigOnes(ulong x, uint n)
return leadingOnes(~x);
}

@system unittest
@safe unittest
{
assert(findContigOnes(0x0000_0000_0000_0300, 2) == 54);

Expand All @@ -1173,14 +1182,15 @@ private uint findContigOnes(ulong x, uint n)
/*
Unconditionally sets the bits from lsb through msb in w to zero.
*/
pure nothrow @safe @nogc
private void setBits(ref ulong w, uint lsb, uint msb)
{
assert(lsb <= msb && msb < 64);
const mask = (ulong.max << lsb) & (ulong.max >> (63 - msb));
w |= mask;
}

@system unittest
@safe unittest
{
ulong w;
w = 0; setBits(w, 0, 63); assert(w == ulong.max);
Expand All @@ -1192,6 +1202,7 @@ private void setBits(ref ulong w, uint lsb, uint msb)
/* Are bits from lsb through msb in w zero? If so, make then 1
and return the resulting w. Otherwise, just return 0.
*/
pure nothrow @safe @nogc
private bool setBitsIfZero(ref ulong w, uint lsb, uint msb)
{
assert(lsb <= msb && msb < 64);
Expand All @@ -1202,6 +1213,7 @@ private bool setBitsIfZero(ref ulong w, uint lsb, uint msb)
}

// Assigns bits in w from lsb through msb to zero.
pure nothrow @safe @nogc
private void resetBits(ref ulong w, uint lsb, uint msb)
{
assert(lsb <= msb && msb < 64);
Expand All @@ -1218,10 +1230,13 @@ private struct BitVector

auto rep() { return _rep; }

@safe @nogc
this(ulong[] data) { _rep = data; }

pure nothrow @safe @nogc
void opSliceAssign(bool b) { _rep[] = b ? ulong.max : 0; }

pure @safe @nogc
void opSliceAssign(bool b, ulong x, ulong y)
{
assert(x <= y && y <= _rep.length * 64);
Expand Down Expand Up @@ -1253,13 +1268,15 @@ private struct BitVector
}
}

@safe @nogc
bool opIndex(ulong x)
{
assert(x < length);
return (_rep[cast(size_t) (x / 64)]
& (0x8000_0000_0000_0000UL >> (x % 64))) != 0;
}

@safe @nogc
void opIndexAssign(bool b, ulong x)
{
assert(x / 64 <= size_t.max);
Expand All @@ -1269,6 +1286,7 @@ private struct BitVector
else _rep[i] &= ~j;
}

nothrow @safe @nogc
ulong length() const
{
return _rep.length * 64;
Expand All @@ -1277,6 +1295,7 @@ private struct BitVector
/* Returns the index of the first 1 to the right of i (including i itself),
or length if not found.
*/
nothrow @safe @nogc
ulong find1(ulong i)
{
assert(i < length);
Expand Down Expand Up @@ -1304,6 +1323,7 @@ private struct BitVector
/* Returns the index of the first 1 to the left of i (including i itself),
or ulong.max if not found.
*/
nothrow @safe @nogc
ulong find1Backward(ulong i)
{
assert(i < length);
Expand All @@ -1329,19 +1349,22 @@ private struct BitVector
}

/// Are all bits zero?
nothrow @safe @nogc
bool allAre0() const
{
foreach (w; _rep) if (w) return false;
return true;
}

/// Are all bits one?
nothrow @safe @nogc
bool allAre1() const
{
foreach (w; _rep) if (w != ulong.max) return false;
return true;
}

nothrow @safe @nogc
ulong findZeros(immutable size_t howMany, ulong start)
{
assert(start < length);
Expand Down Expand Up @@ -1378,7 +1401,7 @@ private struct BitVector
}
}

@system unittest
@safe unittest
{
auto v = BitVector(new ulong[10]);
assert(v.length == 640);
Expand Down
1 change: 0 additions & 1 deletion std/experimental/allocator/building_blocks/bucketizer.d
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ struct Bucketizer(Allocator, size_t min, size_t max, size_t step)
auto b = a.allocate(400);
assert(b.length == 400);
assert(a.owns(b) == Ternary.yes);
void[] p;
a.deallocate(b);
}

Expand Down
14 changes: 14 additions & 0 deletions std/experimental/allocator/building_blocks/fallback_allocator.d
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,17 @@ fallbackAllocator(Primary, Fallback)(auto ref Primary p, auto ref Fallback f)
auto buff = a.allocate(42);
assert((() pure nothrow @safe @nogc => a.owns(buff))() == Ternary.yes);
}

@system unittest
{
import std.experimental.allocator.gc_allocator : GCAllocator;
import std.typecons : Ternary;

auto a = fallbackAllocator(GCAllocator.instance, GCAllocator.instance);
auto b = a.allocate(1020);
assert(b.length == 1020);

void[] p;
assert((() nothrow @safe @nogc => a.resolveInternalPointer(null, p))() == Ternary.no);
assert((() nothrow @safe @nogc => a.resolveInternalPointer(&b[0], p))() == Ternary.yes);
}
4 changes: 3 additions & 1 deletion std/experimental/allocator/building_blocks/null_allocator.d
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct NullAllocator
/**
Returns $(D Ternary.no).
*/
pure nothrow @safe @nogc
Ternary resolveInternalPointer(const void*, ref void[]) shared const
{ return Ternary.no; }
/**
Expand Down Expand Up @@ -81,6 +82,7 @@ struct NullAllocator
import std.typecons : Ternary;
assert(NullAllocator.instance.empty() == Ternary.yes);
assert((() nothrow @safe @nogc => NullAllocator.instance.owns(null))() == Ternary.no);

void[] p;
assert(NullAllocator.instance.resolveInternalPointer(null, p) == Ternary.no);
assert((() nothrow @safe @nogc => NullAllocator.instance.resolveInternalPointer(null, p))() == Ternary.no);
}
17 changes: 17 additions & 0 deletions std/experimental/allocator/building_blocks/segregator.d
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,20 @@ if (Args.length > 3)
assert(b.length == 42);
a.deallocate(b);
}

@system unittest
{
import std.experimental.allocator.gc_allocator : GCAllocator;
import std.typecons : Ternary;

shared Segregator!(1024 * 4, GCAllocator, GCAllocator) a;

auto b = a.allocate(201);
assert(b.length == 201);

void[] p;
assert((() nothrow @safe @nogc => a.resolveInternalPointer(null, p))() == Ternary.no);
assert((() nothrow @safe @nogc => a.resolveInternalPointer(&b[0], p))( ) == Ternary.yes);

a.deallocate(b);
}
20 changes: 17 additions & 3 deletions std/experimental/allocator/gc_allocator.d
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ struct GCAllocator
}

/// Ditto
pure nothrow
pure nothrow @trusted @nogc
Ternary resolveInternalPointer(const void* p, ref void[] result) shared
{
auto r = GC.addrOf(cast(void*) p);
Expand Down Expand Up @@ -151,8 +151,8 @@ struct GCAllocator
scope(exit) GCAllocator.instance.deallocate(buffer);

void[] p;
assert(GCAllocator.instance.resolveInternalPointer(null, p) == Ternary.no);
Ternary r = GCAllocator.instance.resolveInternalPointer(buffer.ptr, p);
assert((() nothrow @safe => GCAllocator.instance.resolveInternalPointer(null, p))() == Ternary.no);
assert((() nothrow @safe => GCAllocator.instance.resolveInternalPointer(&buffer[0], p))() == Ternary.yes);
assert(p.ptr is buffer.ptr && p.length >= buffer.length);

assert(GC.sizeOf(buffer.ptr) == s);
Expand All @@ -166,3 +166,17 @@ struct GCAllocator
// anything above a page is simply rounded up to next page
assert((() nothrow @safe @nogc => GCAllocator.instance.goodAllocSize(4096 * 4 + 1))() == 4096 * 5);
}

nothrow @safe unittest
{
import std.typecons : Ternary;

void[] buffer = GCAllocator.instance.allocate(42);
void[] result;
Ternary found = GCAllocator.instance.resolveInternalPointer(&buffer[0], result);

assert(found == Ternary.yes && &result[0] == &buffer[0] && result.length >= buffer.length);
assert(GCAllocator.instance.resolveInternalPointer(null, result) == Ternary.no);
void *badPtr = (() @trusted => cast(void*)(0xdeadbeef))();
assert(GCAllocator.instance.resolveInternalPointer(badPtr, result) == Ternary.no);
}
Loading