Make bitmapped_block allocate @safe

This commit is contained in:
Eduard Staniloiu 2018-03-29 12:38:05 +00:00 committed by Sebastian Wilzbach
parent 0d45880abe
commit e100cde76f

View file

@ -303,7 +303,8 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
Allocations greater than 64 blocks require a multiword search through the Allocations greater than 64 blocks require a multiword search through the
metadata. metadata.
*/ */
@trusted void[] allocate(const size_t s) pure nothrow @trusted @nogc
void[] allocate(const size_t s)
{ {
const blocks = s.divideRoundUp(blockSize); const blocks = s.divideRoundUp(blockSize);
void[] result = void; void[] result = void;
@ -509,9 +510,10 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
return available; return available;
} }
pure nothrow @safe @nogc
private void[] smallAlloc(uint blocks) private void[] smallAlloc(uint blocks)
{ {
assert(blocks >= 2 && blocks <= 64, text(blocks)); assert(blocks >= 2 && blocks <= 64);
void[] result; void[] result;
foreach (i; _startIdx .. _control.rep.length) foreach (i; _startIdx .. _control.rep.length)
{ {
@ -544,6 +546,7 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
return null; return null;
} }
pure nothrow @safe @nogc
private void[] hugeAlloc(size_t blocks) private void[] hugeAlloc(size_t blocks)
{ {
assert(blocks > 64); assert(blocks > 64);
@ -806,19 +809,21 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
uint blockSize = 64; uint blockSize = 64;
auto a = BitmappedBlock!(chooseAtRuntime, 64)(cast(ubyte[])(r.allocateAll()), blockSize); auto a = BitmappedBlock!(chooseAtRuntime, 64)(cast(ubyte[])(r.allocateAll()), blockSize);
static assert(hasMember!(InSituRegion!(10_240, 64), "allocateAll")); static assert(hasMember!(InSituRegion!(10_240, 64), "allocateAll"));
const b = a.allocate(100); const b = (() pure nothrow @safe @nogc => a.allocate(100))();
assert(b.length == 100); assert(b.length == 100);
} }
@system unittest pure @safe unittest
{ {
import std.typecons : Ternary; import std.typecons : Ternary;
auto a = BitmappedBlock!(64, 64)(new ubyte[10_240]); auto a = (() @trusted => BitmappedBlock!(64, 64)(new ubyte[10_240]))();
assert((() nothrow @safe @nogc => a.empty)() == Ternary.yes); () nothrow @nogc {
assert(a.empty == Ternary.yes);
const b = a.allocate(100); const b = a.allocate(100);
assert(b.length == 100); assert(b.length == 100);
assert((() nothrow @safe @nogc => a.empty)() == Ternary.no); assert(a.empty == Ternary.no);
}();
} }
@system unittest @system unittest
@ -851,10 +856,10 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
blocks = a._blocks; blocks = a._blocks;
// test allocation of 0 bytes // test allocation of 0 bytes
auto x = a.allocate(0); auto x = (() pure nothrow @safe @nogc => a.allocate(0))();
assert(x is null); assert(x is null);
// test allocation of 1 byte // test allocation of 1 byte
x = a.allocate(1); x = (() pure nothrow @safe @nogc => a.allocate(1))();
assert(x.length == 1 || blocks == 0, assert(x.length == 1 || blocks == 0,
text(x.ptr, " ", x.length, " ", a)); text(x.ptr, " ", x.length, " ", a));
assert((() nothrow @nogc => a.deallocateAll())()); assert((() nothrow @nogc => a.deallocateAll())());
@ -864,12 +869,14 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
begin: begin:
foreach (i; 0 .. blocks / blocksAtATime) foreach (i; 0 .. blocks / blocksAtATime)
{ {
auto b = a.allocate(bs * blocksAtATime); auto b = (() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))();
assert(b.length == bs * blocksAtATime, text(i, ": ", b.length)); assert(b.length == bs * blocksAtATime, text(i, ": ", b.length));
} }
assert(a.allocate(bs * blocksAtATime) is null); assert((() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))() is null);
if (a._blocks % blocksAtATime == 0) if (a._blocks % blocksAtATime == 0)
assert(a.allocate(1) is null); {
assert((() pure nothrow @safe @nogc => a.allocate(1))() is null);
}
// Now deallocate all and do it again! // Now deallocate all and do it again!
assert((() nothrow @nogc => a.deallocateAll())()); assert((() nothrow @nogc => a.deallocateAll())());
@ -879,13 +886,15 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
auto v = new void[][blocks / blocksAtATime]; auto v = new void[][blocks / blocksAtATime];
foreach (i; 0 .. blocks / blocksAtATime) foreach (i; 0 .. blocks / blocksAtATime)
{ {
auto b = a.allocate(bs * blocksAtATime); auto b = (() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))();
assert(b.length == bs * blocksAtATime, text(i, ": ", b.length)); assert(b.length == bs * blocksAtATime, text(i, ": ", b.length));
v[i] = b; v[i] = b;
} }
assert(a.allocate(bs * blocksAtATime) is null); assert((() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))() is null);
if (a._blocks % blocksAtATime == 0) if (a._blocks % blocksAtATime == 0)
assert(a.allocate(1) is null); {
assert((() pure nothrow @safe @nogc => a.allocate(1))() is null);
}
foreach (i; 0 .. blocks / blocksAtATime) foreach (i; 0 .. blocks / blocksAtATime)
{ {
@ -894,7 +903,7 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
foreach (i; 0 .. blocks / blocksAtATime) foreach (i; 0 .. blocks / blocksAtATime)
{ {
auto b = a.allocate(bs * blocksAtATime); auto b = (() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))();
assert(b.length == bs * blocksAtATime, text(i, ": ", b.length)); assert(b.length == bs * blocksAtATime, text(i, ": ", b.length));
v[i] = b; v[i] = b;
} }
@ -917,7 +926,7 @@ struct BitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment
{ {
foreach (i; 0 .. blocks / blocksAtATime - 1) foreach (i; 0 .. blocks / blocksAtATime - 1)
{ {
auto b = a.allocate(bs * blocksAtATime); auto b = (() pure nothrow @safe @nogc => a.allocate(bs * blocksAtATime))();
assert(b.length == bs * blocksAtATime, text(i, ": ", b.length)); assert(b.length == bs * blocksAtATime, text(i, ": ", b.length));
(cast(ubyte[]) b)[] = 0xff; (cast(ubyte[]) b)[] = 0xff;
assert((() pure nothrow @safe @nogc => a.expand(b, blocksAtATime * bs))() assert((() pure nothrow @safe @nogc => a.expand(b, blocksAtATime * bs))()
@ -1126,7 +1135,7 @@ nothrow @safe @nogc unittest
import std.typecons : Ternary; import std.typecons : Ternary;
auto a = BitmappedBlock!(64, 8, GCAllocator)(1024 * 64); auto a = BitmappedBlock!(64, 8, GCAllocator)(1024 * 64);
const void[] buff = a.allocate(42); const void[] buff = (() pure nothrow @safe @nogc => a.allocate(42))();
assert((() nothrow @safe @nogc => a.owns(buff))() == Ternary.yes); assert((() nothrow @safe @nogc => a.owns(buff))() == Ternary.yes);
assert((() nothrow @safe @nogc => a.owns(null))() == Ternary.no); assert((() nothrow @safe @nogc => a.owns(null))() == Ternary.no);
@ -1216,13 +1225,13 @@ struct BitmappedBlockWithInternalPointers(
{ {
auto r = _heap.allocate(bytes); auto r = _heap.allocate(bytes);
if (!r.ptr) return r; if (!r.ptr) return r;
immutable block = (r.ptr - _heap._payload.ptr) / _heap.blockSize; immutable block = (() @trusted => (r.ptr - _heap._payload.ptr) / _heap.blockSize)();
immutable blocks = immutable blocks =
(r.length + _heap.blockSize - 1) / _heap.blockSize; (r.length + _heap.blockSize - 1) / _heap.blockSize;
if (!ensureRoomForAllocStart(block + blocks)) if (!ensureRoomForAllocStart(block + blocks))
{ {
// Failed, free r and bailout // Failed, free r and bailout
_heap.deallocate(r); () @trusted { _heap.deallocate(r); r = null; }();
return null; return null;
} }
assert(block < _allocStart.length); assert(block < _allocStart.length);
@ -1360,7 +1369,7 @@ struct BitmappedBlockWithInternalPointers(
auto h = BitmappedBlockWithInternalPointers!(4096)(new ubyte[4096 * 1024]); auto h = BitmappedBlockWithInternalPointers!(4096)(new ubyte[4096 * 1024]);
assert((() nothrow @safe @nogc => h.empty)() == Ternary.yes); assert((() nothrow @safe @nogc => h.empty)() == Ternary.yes);
auto b = h.allocate(123); auto b = (() pure nothrow @safe @nogc => h.allocate(123))();
assert(b.length == 123); assert(b.length == 123);
assert((() nothrow @safe @nogc => h.empty)() == Ternary.no); assert((() nothrow @safe @nogc => h.empty)() == Ternary.no);
@ -1369,7 +1378,7 @@ struct BitmappedBlockWithInternalPointers(
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes); assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
assert(p.ptr is b.ptr); assert(p.ptr is b.ptr);
assert(p.length >= b.length); assert(p.length >= b.length);
b = h.allocate(4096); b = (() pure nothrow @safe @nogc => h.allocate(4096))();
offset = &b[0]; offset = &b[0];
assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes); assert((() nothrow @safe @nogc => h.resolveInternalPointer(offset, p))() == Ternary.yes);
@ -1572,7 +1581,7 @@ private struct BitVector
/* Returns the index of the first 1 to the right of i (including i itself), /* Returns the index of the first 1 to the right of i (including i itself),
or length if not found. or length if not found.
*/ */
nothrow @safe @nogc pure nothrow @safe @nogc
ulong find1(ulong i) ulong find1(ulong i)
{ {
assert(i < length); assert(i < length);
@ -1600,7 +1609,7 @@ private struct BitVector
/* Returns the index of the first 1 to the left of i (including i itself), /* Returns the index of the first 1 to the left of i (including i itself),
or ulong.max if not found. or ulong.max if not found.
*/ */
nothrow @safe @nogc pure nothrow @safe @nogc
ulong find1Backward(ulong i) ulong find1Backward(ulong i)
{ {
assert(i < length); assert(i < length);
@ -1634,14 +1643,14 @@ private struct BitVector
} }
/// Are all bits one? /// Are all bits one?
nothrow @safe @nogc pure nothrow @safe @nogc
bool allAre1() const bool allAre1() const
{ {
foreach (w; _rep) if (w != ulong.max) return false; foreach (w; _rep) if (w != ulong.max) return false;
return true; return true;
} }
nothrow @safe @nogc pure nothrow @safe @nogc
ulong findZeros(immutable size_t howMany, ulong start) ulong findZeros(immutable size_t howMany, ulong start)
{ {
assert(start < length); assert(start < length);