blob: e19efc54c0d0bd2d8fc0c17e884ca0b5f4310ac4 [file] [log] [blame]
@system unittest
{
import std.experimental.allocator;
// Install a new allocator that is faster for 128-byte allocations.
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.gc_allocator : GCAllocator;
auto oldAllocator = theAllocator;
scope(exit) theAllocator = oldAllocator;
theAllocator = allocatorObject(FreeList!(GCAllocator, 128)());
// Use the now changed allocator to allocate an array
const ubyte[] arr = theAllocator.makeArray!ubyte(128);
assert(arr.ptr);
//...
}
@system unittest
{
import std.experimental.allocator;
// Dynamically allocate one integer
const int* p1 = theAllocator.make!int;
// It's implicitly initialized with its .init value
assert(*p1 == 0);
// Dynamically allocate one double, initialize to 42.5
const double* p2 = theAllocator.make!double(42.5);
assert(*p2 == 42.5);
// Dynamically allocate a struct
static struct Point
{
int x, y, z;
}
// Use the generated constructor taking field values in order
const Point* p = theAllocator.make!Point(1, 2);
assert(p.x == 1 && p.y == 2 && p.z == 0);
// Dynamically allocate a class object
static class Customer
{
uint id = uint.max;
this() {}
this(uint id) { this.id = id; }
// ...
}
Customer cust = theAllocator.make!Customer;
assert(cust.id == uint.max); // default initialized
cust = theAllocator.make!Customer(42);
assert(cust.id == 42);
// explicit passing of outer pointer
static class Outer
{
int x = 3;
class Inner
{
auto getX() { return x; }
}
}
auto outer = theAllocator.make!Outer();
auto inner = theAllocator.make!(Outer.Inner)(outer);
assert(outer.x == inner.getX);
}
@system unittest
{
import std.experimental.allocator;
import std.algorithm.comparison : equal;
static void test(T)()
{
T[] a = theAllocator.makeArray!T(2);
assert(a.equal([0, 0]));
a = theAllocator.makeArray!T(3, 42);
assert(a.equal([42, 42, 42]));
import std.range : only;
a = theAllocator.makeArray!T(only(42, 43, 44));
assert(a.equal([42, 43, 44]));
}
test!int();
test!(shared int)();
test!(const int)();
test!(immutable int)();
}
@system unittest
{
import std.experimental.allocator;
auto arr = theAllocator.makeArray!int([1, 2, 3]);
assert(theAllocator.expandArray(arr, 2));
assert(arr == [1, 2, 3, 0, 0]);
import std.range : only;
assert(theAllocator.expandArray(arr, only(4, 5)));
assert(arr == [1, 2, 3, 0, 0, 4, 5]);
}
@system unittest
{
import std.experimental.allocator;
int[] a = theAllocator.makeArray!int(100, 42);
assert(a.length == 100);
assert(theAllocator.shrinkArray(a, 98));
assert(a.length == 2);
assert(a == [42, 42]);
}
@system unittest
{
import std.experimental.allocator;
import std.experimental.allocator.mallocator : Mallocator;
auto mArray = Mallocator.instance.makeMultidimensionalArray!int(2, 3, 6);
// deallocate when exiting scope
scope(exit)
{
Mallocator.instance.disposeMultidimensionalArray(mArray);
}
assert(mArray.length == 2);
foreach (lvl2Array; mArray)
{
assert(lvl2Array.length == 3);
foreach (lvl3Array; lvl2Array)
assert(lvl3Array.length == 6);
}
}
@system unittest
{
import std.experimental.allocator;
struct TestAllocator
{
import std.experimental.allocator.common : platformAlignment;
import std.experimental.allocator.mallocator : Mallocator;
alias allocator = Mallocator.instance;
private static struct ByteRange
{
void* ptr;
size_t length;
}
private ByteRange[] _allocations;
enum uint alignment = platformAlignment;
void[] allocate(size_t numBytes)
{
auto ret = allocator.allocate(numBytes);
_allocations ~= ByteRange(ret.ptr, ret.length);
return ret;
}
bool deallocate(void[] bytes)
{
import std.algorithm.mutation : remove;
import std.algorithm.searching : canFind;
bool pred(ByteRange other)
{ return other.ptr == bytes.ptr && other.length == bytes.length; }
assert(_allocations.canFind!pred);
_allocations = _allocations.remove!pred;
return allocator.deallocate(bytes);
}
~this()
{
assert(!_allocations.length);
}
}
TestAllocator allocator;
auto mArray = allocator.makeMultidimensionalArray!int(2, 3, 5, 6, 7, 2);
allocator.disposeMultidimensionalArray(mArray);
}
@system unittest
{
import std.experimental.allocator;
import std.experimental.allocator.mallocator : Mallocator;
RCIAllocator a = allocatorObject(Mallocator.instance);
auto b = a.allocate(100);
assert(b.length == 100);
assert(a.deallocate(b));
// The in-situ region must be used by pointer
import std.experimental.allocator.building_blocks.region : InSituRegion;
auto r = InSituRegion!1024();
a = allocatorObject(&r);
b = a.allocate(200);
assert(b.length == 200);
// In-situ regions can deallocate the last allocation
assert(a.deallocate(b));
}
@system unittest
{
import std.experimental.allocator;
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.gc_allocator : GCAllocator;
import std.experimental.allocator.mallocator : Mallocator;
static assert(!is(ThreadLocal!Mallocator));
static assert(!is(ThreadLocal!GCAllocator));
alias Allocator = ThreadLocal!(FreeList!(GCAllocator, 0, 8));
auto b = Allocator.instance.allocate(5);
static assert(__traits(hasMember, Allocator, "allocate"));
}
@system unittest
{
import std.experimental.allocator;
import std.experimental.allocator.building_blocks.allocator_list : AllocatorList;
import std.experimental.allocator.building_blocks.bitmapped_block : BitmappedBlock;
import std.experimental.allocator.building_blocks.segregator : Segregator;
import std.experimental.allocator.building_blocks.bucketizer : Bucketizer;
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.gc_allocator : GCAllocator;
/// Define an allocator bound to the built-in GC.
auto alloc = allocatorObject(GCAllocator.instance);
auto b = alloc.allocate(42);
assert(b.length == 42);
assert(alloc.deallocate(b));
import std.algorithm.comparison : max;
// Define an elaborate allocator and bind it to the class API.
alias FList = FreeList!(GCAllocator, 0, unbounded);
alias A = ThreadLocal!(
Segregator!(
8, FreeList!(GCAllocator, 0, 8),
128, Bucketizer!(FList, 1, 128, 16),
256, Bucketizer!(FList, 129, 256, 32),
512, Bucketizer!(FList, 257, 512, 64),
1024, Bucketizer!(FList, 513, 1024, 128),
2048, Bucketizer!(FList, 1025, 2048, 256),
3584, Bucketizer!(FList, 2049, 3584, 512),
4072 * 1024, AllocatorList!(
(n) => BitmappedBlock!(4096)(cast(ubyte[]) GCAllocator.instance.allocate(
max(n, 4072 * 1024)))),
GCAllocator
)
);
auto alloc2 = allocatorObject(A.instance);
b = alloc2.allocate(101);
assert(alloc2.deallocate(b));
}