Add Mallocator as an alternative allocator
This commit is contained in:
parent
f4145abfd1
commit
d0ada39fa7
@ -95,7 +95,7 @@ private struct Range(E)
|
|||||||
--end;
|
--end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref inout(E) opIndex(in size_t i) inout @trusted
|
ref inout(E) opIndex(const size_t i) inout @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i < length);
|
assert(i < length);
|
||||||
@ -115,7 +115,7 @@ private struct Range(E)
|
|||||||
return typeof(return)(begin, end);
|
return typeof(return)(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range opSlice(in size_t i, in size_t j) @trusted
|
Range opSlice(const size_t i, const size_t j) @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -126,7 +126,7 @@ private struct Range(E)
|
|||||||
return typeof(return)(begin + i, begin + j);
|
return typeof(return)(begin + i, begin + j);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range!(const E) opSlice(in size_t i, in size_t j) const @trusted
|
Range!(const E) opSlice(const size_t i, const size_t j) const @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -277,7 +277,7 @@ struct Vector(T)
|
|||||||
* init = Initial value to fill the vector with.
|
* init = Initial value to fill the vector with.
|
||||||
* allocator = Allocator.
|
* allocator = Allocator.
|
||||||
*/
|
*/
|
||||||
this(in size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted
|
this(const size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
reserve(len);
|
reserve(len);
|
||||||
@ -286,7 +286,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
this(in size_t len, shared Allocator allocator = defaultAllocator)
|
this(const size_t len, shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
length = len;
|
length = len;
|
||||||
@ -400,7 +400,7 @@ struct Vector(T)
|
|||||||
* Params:
|
* Params:
|
||||||
* len = New length.
|
* len = New length.
|
||||||
*/
|
*/
|
||||||
@property void length(in size_t len) @trusted
|
@property void length(const size_t len) @trusted
|
||||||
{
|
{
|
||||||
if (len == length)
|
if (len == length)
|
||||||
{
|
{
|
||||||
@ -457,7 +457,7 @@ struct Vector(T)
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Desired size.
|
* size = Desired size.
|
||||||
*/
|
*/
|
||||||
void reserve(in size_t size) @trusted
|
void reserve(const size_t size) @trusted
|
||||||
{
|
{
|
||||||
if (capacity_ >= size)
|
if (capacity_ >= size)
|
||||||
{
|
{
|
||||||
@ -515,7 +515,7 @@ struct Vector(T)
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Desired size.
|
* size = Desired size.
|
||||||
*/
|
*/
|
||||||
void shrink(in size_t size) @trusted
|
void shrink(const size_t size) @trusted
|
||||||
{
|
{
|
||||||
if (capacity_ <= size)
|
if (capacity_ <= size)
|
||||||
{
|
{
|
||||||
@ -541,14 +541,6 @@ struct Vector(T)
|
|||||||
v.insertBack(3);
|
v.insertBack(3);
|
||||||
assert(v.capacity == 5);
|
assert(v.capacity == 5);
|
||||||
assert(v.length == 2);
|
assert(v.length == 2);
|
||||||
|
|
||||||
v.shrink(4);
|
|
||||||
assert(v.capacity == 4);
|
|
||||||
assert(v.length == 2);
|
|
||||||
|
|
||||||
v.shrink(1);
|
|
||||||
assert(v.capacity == 2);
|
|
||||||
assert(v.length == 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -588,7 +580,7 @@ struct Vector(T)
|
|||||||
*
|
*
|
||||||
* Returns: The number of elements removed
|
* Returns: The number of elements removed
|
||||||
*/
|
*/
|
||||||
size_t removeBack(in size_t howMany)
|
size_t removeBack(const size_t howMany)
|
||||||
out (removed)
|
out (removed)
|
||||||
{
|
{
|
||||||
assert(removed <= howMany);
|
assert(removed <= howMany);
|
||||||
@ -952,7 +944,7 @@ struct Vector(T)
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE length > pos)
|
* Precondition: $(D_INLINECODE length > pos)
|
||||||
*/
|
*/
|
||||||
ref T opIndexAssign(ref T value, in size_t pos)
|
ref T opIndexAssign(ref T value, const size_t pos)
|
||||||
{
|
{
|
||||||
return opIndex(pos) = value;
|
return opIndex(pos) = value;
|
||||||
}
|
}
|
||||||
@ -965,7 +957,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
T opIndexAssign(T value, in size_t pos)
|
T opIndexAssign(T value, const size_t pos)
|
||||||
{
|
{
|
||||||
return opIndexAssign(value, pos);
|
return opIndexAssign(value, pos);
|
||||||
}
|
}
|
||||||
@ -1030,7 +1022,7 @@ struct Vector(T)
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE length > pos)
|
* Precondition: $(D_INLINECODE length > pos)
|
||||||
*/
|
*/
|
||||||
ref inout(T) opIndex(in size_t pos) inout @trusted
|
ref inout(T) opIndex(const size_t pos) inout @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(length > pos);
|
assert(length > pos);
|
||||||
@ -1083,7 +1075,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
bool opEquals()(in auto ref typeof(this) that) const @trusted
|
bool opEquals()(const auto ref typeof(this) that) const @trusted
|
||||||
{
|
{
|
||||||
return equal(vector[0 .. length_], that.vector[0 .. that.length_]);
|
return equal(vector[0 .. length_], that.vector[0 .. that.length_]);
|
||||||
}
|
}
|
||||||
@ -1308,7 +1300,7 @@ struct Vector(T)
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE i <= j && j <= length)
|
* Precondition: $(D_INLINECODE i <= j && j <= length)
|
||||||
*/
|
*/
|
||||||
Range!T opSlice(in size_t i, in size_t j) @trusted
|
Range!T opSlice(const size_t i, const size_t j) @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -1320,7 +1312,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!(const T) opSlice(in size_t i, in size_t j) const @trusted
|
Range!(const T) opSlice(const size_t i, const size_t j) const @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -1390,7 +1382,7 @@ struct Vector(T)
|
|||||||
* Precondition: $(D_INLINECODE i <= j && j <= length
|
* Precondition: $(D_INLINECODE i <= j && j <= length
|
||||||
* && value.length == j - i)
|
* && value.length == j - i)
|
||||||
*/
|
*/
|
||||||
Range!T opSliceAssign(R)(R value, in size_t i, in size_t j) @trusted
|
Range!T opSliceAssign(R)(R value, const size_t i, const size_t j) @trusted
|
||||||
if (!isInfinite!R
|
if (!isInfinite!R
|
||||||
&& isInputRange!R
|
&& isInputRange!R
|
||||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||||
@ -1407,13 +1399,13 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!T opSliceAssign(size_t R)(T[R] value, in size_t i, in size_t j)
|
Range!T opSliceAssign(size_t R)(T[R] value, const size_t i, const size_t j)
|
||||||
{
|
{
|
||||||
return opSliceAssign!(T[])(value[], i, j);
|
return opSliceAssign!(T[])(value[], i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!T opSliceAssign(ref T value, in size_t i, in size_t j) @trusted
|
Range!T opSliceAssign(ref T value, const size_t i, const size_t j) @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -1426,7 +1418,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!T opSliceAssign(T value, in size_t i, in size_t j)
|
Range!T opSliceAssign(T value, const size_t i, const size_t j)
|
||||||
{
|
{
|
||||||
return opSliceAssign(value, i, j);
|
return opSliceAssign(value, i, j);
|
||||||
}
|
}
|
||||||
@ -1561,7 +1553,7 @@ unittest
|
|||||||
}
|
}
|
||||||
struct ConstEqualsStruct
|
struct ConstEqualsStruct
|
||||||
{
|
{
|
||||||
int opEquals(in typeof(this) that) const @nogc
|
int opEquals(const typeof(this) that) const @nogc
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
185
source/tanya/memory/mallocator.d
Normal file
185
source/tanya/memory/mallocator.d
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
*/
|
||||||
|
module tanya.memory.mallocator;
|
||||||
|
|
||||||
|
import core.stdc.stdlib;
|
||||||
|
import std.algorithm.comparison;
|
||||||
|
import tanya.memory.allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for malloc/realloc/free from the C standard library.
|
||||||
|
*/
|
||||||
|
final class Mallocator : Allocator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Allocates $(D_PARAM size) bytes of memory.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* size = Amount of memory to allocate.
|
||||||
|
*
|
||||||
|
* Returns: The pointer to the new allocated memory.
|
||||||
|
*/
|
||||||
|
void[] allocate(in size_t size) shared nothrow @nogc
|
||||||
|
{
|
||||||
|
if (!size)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
auto p = malloc(size + psize);
|
||||||
|
|
||||||
|
return p is null ? null : p[psize .. psize + size];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow unittest
|
||||||
|
{
|
||||||
|
auto p = Mallocator.instance.allocate(20);
|
||||||
|
|
||||||
|
assert(p.length == 20);
|
||||||
|
|
||||||
|
Mallocator.instance.deallocate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deallocates a memory block.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* p = A pointer to the memory block to be freed.
|
||||||
|
*
|
||||||
|
* Returns: Whether the deallocation was successful.
|
||||||
|
*/
|
||||||
|
bool deallocate(void[] p) shared nothrow @nogc
|
||||||
|
{
|
||||||
|
if (p !is null)
|
||||||
|
{
|
||||||
|
free(p.ptr - psize);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow unittest
|
||||||
|
{
|
||||||
|
void[] p;
|
||||||
|
assert(Mallocator.instance.deallocate(p));
|
||||||
|
|
||||||
|
p = Mallocator.instance.allocate(10);
|
||||||
|
assert(Mallocator.instance.deallocate(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reallocating in place isn't supported.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* p = A pointer to the memory block.
|
||||||
|
* size = Size of the reallocated block.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD false).
|
||||||
|
*/
|
||||||
|
bool reallocateInPlace(ref void[] p, const size_t size) shared nothrow @nogc
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases or decreases the size of a memory block.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* p = A pointer to the memory block.
|
||||||
|
* size = Size of the reallocated block.
|
||||||
|
*
|
||||||
|
* Returns: Whether the reallocation was successful.
|
||||||
|
*/
|
||||||
|
bool reallocate(ref void[] p, const size_t size) shared nothrow @nogc
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
if (deallocate(p))
|
||||||
|
{
|
||||||
|
p = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p is null)
|
||||||
|
{
|
||||||
|
p = allocate(size);
|
||||||
|
return p is null ? false : true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto r = realloc(p.ptr - psize, size + psize);
|
||||||
|
|
||||||
|
if (r !is null)
|
||||||
|
{
|
||||||
|
p = r[psize .. psize + size];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow unittest
|
||||||
|
{
|
||||||
|
void[] p;
|
||||||
|
|
||||||
|
assert(Mallocator.instance.reallocate(p, 20));
|
||||||
|
assert(p.length == 20);
|
||||||
|
|
||||||
|
assert(Mallocator.instance.reallocate(p, 30));
|
||||||
|
assert(p.length == 30);
|
||||||
|
|
||||||
|
assert(Mallocator.instance.reallocate(p, 10));
|
||||||
|
assert(p.length == 10);
|
||||||
|
|
||||||
|
assert(Mallocator.instance.reallocate(p, 0));
|
||||||
|
assert(p is null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: The alignment offered.
|
||||||
|
*/
|
||||||
|
@property uint alignment() shared const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return cast(uint) max(double.alignof, real.alignof);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static allocator instance and initializer.
|
||||||
|
*
|
||||||
|
* Returns: The global $(D_PSYMBOL Allocator) instance.
|
||||||
|
*/
|
||||||
|
static @property ref shared(Mallocator) instance() @nogc nothrow
|
||||||
|
{
|
||||||
|
if (instance_ is null)
|
||||||
|
{
|
||||||
|
immutable size = __traits(classInstanceSize, Mallocator) + psize;
|
||||||
|
void* p = malloc(size);
|
||||||
|
|
||||||
|
if (p !is null)
|
||||||
|
{
|
||||||
|
p[psize .. size] = typeid(Mallocator).initializer[];
|
||||||
|
instance_ = cast(shared Mallocator) p[psize .. size].ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow unittest
|
||||||
|
{
|
||||||
|
assert(instance is instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum psize = 8;
|
||||||
|
|
||||||
|
private shared static Mallocator instance_;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user