Home

Awesome

CI

The memutils library provides a set of 4 enhanced allocators tweaked for better performance depending on the scope. A new allocation syntax comes with many benefits, including the easy replacement of allocators.

The allocator-friendly containers are:

The allocator-friendly lifetime management objects are:

The RefCounted object makes use of a new mixin template, available to replace the alias this m_obj; idiom, it can be found in memutils.helpers. It enables the proxying of operators (including operator overloads) from the underlying object. Type inference will not work for callback delegates used in methods such as opApply, but essentially it allows the most similar experience to base interfaces.

Examples:

struct MyString {
 mixin Embed!m_obj; // This object impersonates a string!
 string m_obj;

 // Custom methods extend the features of the `string` base type!
 void toInt() { }
}
void main() {
 string ms = MyString.init; // implicit casting also works
 MyString ms2 = MyString("Hello");

 // You can "dereference" the underlying object with `opStar()`
 assert(is(typeof(*ms2) == string));
}

You can use AppMem, ThreadMem, SecureMem for array or object allocations!

 A a = ThreadMem.alloc!A();
 // do something with "a"
 ThreadMem.free(a);

 ubyte[] ub = AppMem.alloc!(ubyte[])(150);
 assert(ub.length == 150);

The Vector container, like every other container, takes ownership of the underlying data.

 string val;
 string gcVal;
 {
 	Vector!char data; // Uses a thread-local allocator by default (LocklessFreeList)
 	data ~= "Hello there";
 	val = data[]; // use opslice [] operator to access the underlying array.
 	gcVal = data[].idup; // move it to the GC to escape the scope towards the unknown!
 }
 assert(gcVal == "Hello there");
 writeln(val); // SEGMENTATION FAULT: The data was collected! (this is a good thing).

The Array type is a RefCounted!(Vector), it allows a hash map to take partial ownership, because objects marked @disable this(this) are not compatible with the containers.

{
	HashMap!(string, Array!char) hmap;
	hmap["hey"] = Array!(char)("Hello there!");
	assert(hmap["hey"][] == "Hello there!");
}

Using the GC (AppMem) for containers will still call free() by default, you must copy the data if you want it to escape the scope.

string gcVal;
{
	Vector!(char, AppMem) data;
	data ~= "Hello there";
	gcVal = data[].idup;
}
assert(gcVal == "Hello there");

The Unique lifetime management object takes ownership of GC-allocated memory by default. It will free the memory explicitely when it goes out of scope, and it works as an object member!

class A {
	int a;
}
A a = new A;
{ Unique!A = a; }
assert(a is null);

See source/tests.d for more examples.