| @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)); | |
| } | |