Skip to content

Commit 9d59443

Browse files
thewilsonatordenisa.ciobanu1208
authored and
denisa.ciobanu1208
committed
Make KRR allocate @safe
1 parent 08638dd commit 9d59443

File tree

1 file changed

+46
-26
lines changed

1 file changed

+46
-26
lines changed

std/experimental/allocator/building_blocks/kernighan_ritchie.d

+46-26
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
Source: $(PHOBOSSRC std/experimental/allocator/building_blocks/kernighan_ritchie.d)
44
*/
55
module std.experimental.allocator.building_blocks.kernighan_ritchie;
6-
import std.experimental.allocator.building_blocks.null_allocator :
7-
NullAllocator;
6+
import std.experimental.allocator.building_blocks.null_allocator;
87

98
//debug = KRRegion;
109
debug(KRRegion) import std.stdio;
@@ -111,18 +110,21 @@ struct KRRegion(ParentAllocator = NullAllocator)
111110

112111
this(this) @disable;
113112

113+
pure nothrow @trusted @nogc
114114
void[] payload() inout
115115
{
116116
return (cast(ubyte*) &this)[0 .. size];
117117
}
118118

119+
pure nothrow @trusted @nogc
119120
bool adjacent(in Node* right) const
120121
{
121122
assert(right);
122123
auto p = payload;
123124
return p.ptr < right && right < p.ptr + p.length + Node.sizeof;
124125
}
125126

127+
pure nothrow @trusted @nogc
126128
bool coalesce(void* memoryEnd = null)
127129
{
128130
// Coalesce the last node before the memory end with any possible gap
@@ -139,6 +141,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
139141
return true;
140142
}
141143

144+
@safe
142145
Tuple!(void[], Node*) allocateHere(size_t bytes)
143146
{
144147
assert(bytes >= Node.sizeof);
@@ -152,7 +155,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
152155
if (leftover >= Node.sizeof)
153156
{
154157
// There's room for another node
155-
auto newNode = cast(Node*) ((cast(ubyte*) &this) + bytes);
158+
auto newNode = (() @trusted => cast(Node*) ((cast(ubyte*) &this) + bytes))();
156159
newNode.size = leftover;
157160
newNode.next = next == &this ? newNode : next;
158161
assert(next);
@@ -358,7 +361,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
358361
/// Ditto
359362
static if (!is(ParentAllocator == NullAllocator)
360363
&& hasMember!(ParentAllocator, "deallocate"))
361-
~this()
364+
@trusted ~this()
362365
{
363366
parent.deallocate(payload);
364367
}
@@ -396,6 +399,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
396399
397400
Returns: A word-aligned buffer of `n` bytes, or `null`.
398401
*/
402+
@safe
399403
void[] allocate(size_t n)
400404
{
401405
if (!n || !root) return null;
@@ -413,7 +417,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
413417
immutable balance = root.size - actualBytes;
414418
if (balance >= Node.sizeof)
415419
{
416-
auto newRoot = cast(Node*) (result + actualBytes);
420+
auto newRoot = (() @trusted => cast(Node*) (result + actualBytes))();
417421
newRoot.next = root.next;
418422
newRoot.size = balance;
419423
root = newRoot;
@@ -423,7 +427,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
423427
root = null;
424428
switchToFreeList;
425429
}
426-
return result[0 .. n];
430+
return (() @trusted => result[0 .. n])();
427431
}
428432

429433
// Not enough memory, switch to freelist mode and fall through
@@ -554,6 +558,7 @@ struct KRRegion(ParentAllocator = NullAllocator)
554558
at the front of the free list. These blocks get coalesced, whether
555559
`allocateAll` succeeds or fails due to fragmentation.
556560
*/
561+
557562
void[] allocateAll()
558563
{
559564
if (regionMode) switchToFreeList;
@@ -647,7 +652,7 @@ fronting the GC allocator.
647652
import std.experimental.allocator.gc_allocator : GCAllocator;
648653
import std.typecons : Ternary;
649654
// KRRegion fronting a general-purpose allocator
650-
align(KRRegion!().alignment) ubyte[1024 * 128] buf;
655+
ubyte[1024 * 128] buf;
651656
auto alloc = fallbackAllocator(KRRegion!()(buf), GCAllocator.instance);
652657
auto b = alloc.allocate(100);
653658
assert(b.length == 100);
@@ -669,6 +674,7 @@ it actually returns memory to the operating system when possible.
669674
import std.algorithm.comparison : max;
670675
import std.experimental.allocator.building_blocks.allocator_list
671676
: AllocatorList;
677+
import std.experimental.allocator.gc_allocator : GCAllocator;
672678
import std.experimental.allocator.mmap_allocator : MmapAllocator;
673679
AllocatorList!(n => KRRegion!MmapAllocator(max(n * 16, 1024 * 1024))) alloc;
674680
}
@@ -678,6 +684,7 @@ it actually returns memory to the operating system when possible.
678684
import std.algorithm.comparison : max;
679685
import std.experimental.allocator.building_blocks.allocator_list
680686
: AllocatorList;
687+
import std.experimental.allocator.gc_allocator : GCAllocator;
681688
import std.experimental.allocator.mallocator : Mallocator;
682689
import std.typecons : Ternary;
683690
/*
@@ -710,6 +717,7 @@ it actually returns memory to the operating system when possible.
710717
import std.algorithm.comparison : max;
711718
import std.experimental.allocator.building_blocks.allocator_list
712719
: AllocatorList;
720+
import std.experimental.allocator.gc_allocator : GCAllocator;
713721
import std.experimental.allocator.mmap_allocator : MmapAllocator;
714722
import std.typecons : Ternary;
715723
/*
@@ -742,7 +750,6 @@ it actually returns memory to the operating system when possible.
742750
}
743751
}
744752

745-
version (StdUnittest)
746753
@system unittest
747754
{
748755
import std.algorithm.comparison : max;
@@ -754,16 +761,17 @@ version (StdUnittest)
754761
n => KRRegion!GCAllocator(max(n * 16, 1024 * 1024)))());
755762
}
756763

757-
@system unittest
764+
@trusted unittest
758765
{
759766
import std.experimental.allocator.gc_allocator : GCAllocator;
760-
761767
auto alloc = KRRegion!GCAllocator(1024 * 1024);
762768

769+
770+
763771
void[][] array;
764772
foreach (i; 1 .. 4)
765773
{
766-
array ~= alloc.allocate(i);
774+
array ~= (() nothrow @safe => alloc.allocate(i))();
767775
assert(array[$ - 1].length == i);
768776
}
769777
() nothrow @nogc { alloc.deallocate(array[1]); }();
@@ -778,11 +786,11 @@ version (StdUnittest)
778786
import std.typecons : Ternary;
779787
auto alloc = KRRegion!()(
780788
cast(ubyte[])(GCAllocator.instance.allocate(1024 * 1024)));
781-
const store = alloc.allocate(KRRegion!().sizeof);
789+
const store = (() pure nothrow @safe @nogc => alloc.allocate(KRRegion!().sizeof))();
782790
auto p = cast(KRRegion!()* ) store.ptr;
783-
import core.lifetime : emplace;
784791
import core.stdc.string : memcpy;
785-
import std.conv : text;
792+
import std.algorithm.mutation : move;
793+
import std.conv : text, emplace;
786794

787795
memcpy(p, &alloc, alloc.sizeof);
788796
emplace(&alloc);
@@ -791,7 +799,7 @@ version (StdUnittest)
791799
foreach (i; 0 .. array.length)
792800
{
793801
auto length = 100 * i + 1;
794-
array[i] = p.allocate(length);
802+
array[i] = (() pure nothrow @safe @nogc => p.allocate(length))();
795803
assert(array[i].length == length, text(array[i].length));
796804
assert((() pure nothrow @safe @nogc => p.owns(array[i]))() == Ternary.yes);
797805
}
@@ -820,14 +828,16 @@ version (StdUnittest)
820828
assert(p.length == 1024 * 1024);
821829
}
822830

831+
823832
@system unittest
824833
{
825-
import std.random : randomCover;
834+
import std.experimental.allocator.building_blocks;
835+
import std.random;
826836
import std.typecons : Ternary;
827837

828838
// Both sequences must work on either system
829839

830-
// A sequence of allocs which generates the error described in https://issues.dlang.org/show_bug.cgi?id=16564
840+
// A sequence of allocs which generates the error described in issue 16564
831841
// that is a gap at the end of buf from the perspective of the allocator
832842

833843
// for 64 bit systems (leftover balance = 8 bytes < 16)
@@ -837,16 +847,16 @@ version (StdUnittest)
837847
int[] sizes32 = [81412, 107068, 49892, 23768];
838848

839849

840-
void test(int[] sizes)
850+
@system void test(int[] sizes)
841851
{
842852
align(size_t.sizeof) ubyte[256 * 1024] buf;
843-
auto a = KRRegion!()(buf);
853+
auto a = (() @trusted => createAllocator(buf))();
844854

845855
void[][] bufs;
846856

847857
foreach (size; sizes)
848858
{
849-
bufs ~= a.allocate(size);
859+
bufs ~= (() pure nothrow @safe @nogc => a.allocate(size))();
850860
}
851861

852862
foreach (b; bufs.randomCover)
@@ -857,12 +867,22 @@ version (StdUnittest)
857867
assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.yes);
858868
}
859869

860-
test(sizes64);
861-
test(sizes32);
870+
() @trusted {
871+
test(sizes64);
872+
test(sizes32);
873+
}();
862874
}
863875

864-
@system unittest
876+
@system KRRegion!NullAllocator createAllocator(ubyte[] buf)
877+
{
878+
return KRRegion!NullAllocator(buf);
879+
}
880+
881+
882+
@safe unittest
865883
{
884+
import std.experimental.allocator.building_blocks;
885+
import std.random;
866886
import std.typecons : Ternary;
867887

868888
// For 64 bits, we allocate in multiples of 8, but the minimum alloc size is 16.
@@ -886,11 +906,11 @@ version (StdUnittest)
886906

887907
foreach (size; sizes)
888908
{
889-
bufs ~= a.allocate(size);
909+
bufs ~= (() pure nothrow @safe @nogc => a.allocate(size))();
890910
}
891911

892912
() nothrow @nogc { a.deallocate(bufs[1]); }();
893-
bufs ~= a.allocate(sizes[1] - word);
913+
bufs ~= (() pure nothrow @safe @nogc => a.allocate(sizes[1] - word))();
894914

895915
() nothrow @nogc { a.deallocate(bufs[0]); }();
896916
foreach (i; 2 .. bufs.length)
@@ -916,7 +936,7 @@ version (StdUnittest)
916936
@system unittest
917937
{ import std.typecons : Ternary;
918938

919-
align(KRRegion!().alignment) ubyte[1024] b;
939+
ubyte[1024] b;
920940
auto alloc = KRRegion!()(b);
921941

922942
auto k = alloc.allocate(128);

0 commit comments

Comments
 (0)