Implement pure onOutOfMemory
This commit is contained in:
parent
87bfd77373
commit
5d6f8e5299
@ -27,7 +27,10 @@ Tanya consists of the following packages and (top-level) modules:
|
|||||||
* `async`: Event loop (epoll, kqueue and IOCP).
|
* `async`: Event loop (epoll, kqueue and IOCP).
|
||||||
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
||||||
string, Hash set.
|
string, Hash set.
|
||||||
|
* `conv`: This module provides functions for converting between different
|
||||||
|
types.
|
||||||
* `encoding`: This package provides tools to work with text encodings.
|
* `encoding`: This package provides tools to work with text encodings.
|
||||||
|
* `exception`: Common exceptions and errors.
|
||||||
* `format`: Formatting and conversion functions.
|
* `format`: Formatting and conversion functions.
|
||||||
* `math`: Arbitrary precision integer and a set of functions.
|
* `math`: Arbitrary precision integer and a set of functions.
|
||||||
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
module tanya.container.array;
|
module tanya.container.array;
|
||||||
|
|
||||||
import core.checkedint;
|
import core.checkedint;
|
||||||
import core.exception;
|
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
|
||||||
import std.meta;
|
import std.meta;
|
||||||
|
import tanya.exception;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
@ -501,7 +500,7 @@ struct Array(T)
|
|||||||
buf = allocator.allocate(byteSize);
|
buf = allocator.allocate(byteSize);
|
||||||
if (buf is null)
|
if (buf is null)
|
||||||
{
|
{
|
||||||
onOutOfMemoryErrorNoGC();
|
onOutOfMemoryError();
|
||||||
}
|
}
|
||||||
scope (failure)
|
scope (failure)
|
||||||
{
|
{
|
||||||
@ -708,9 +707,12 @@ struct Array(T)
|
|||||||
size_t insertBack(R)(ref R el) @trusted
|
size_t insertBack(R)(ref R el) @trusted
|
||||||
if (isImplicitlyConvertible!(R, T))
|
if (isImplicitlyConvertible!(R, T))
|
||||||
{
|
{
|
||||||
reserve(this.length_ + 1);
|
this.length = this.length + 1;
|
||||||
emplace(this.data + this.length_, el);
|
scope (failure)
|
||||||
++this.length_;
|
{
|
||||||
|
this.length = this.length - 1;
|
||||||
|
}
|
||||||
|
opIndex(this.length - 1) = el;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.container.queue;
|
module tanya.container.queue;
|
||||||
|
|
||||||
import core.exception;
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
|
import tanya.exception;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
|
|
||||||
|
@ -361,14 +361,14 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("\u10437"w);
|
auto s = String("\u10437"w);
|
||||||
assert(s == "\u10437");
|
assert(s == "\u10437");
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Отказаться от вина - в этом страшная вина."d);
|
auto s = String("Отказаться от вина - в этом страшная вина."d);
|
||||||
assert(s == "Отказаться от вина - в этом страшная вина.");
|
assert(s == "Отказаться от вина - в этом страшная вина.");
|
||||||
@ -392,8 +392,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE allocator is null).
|
* Precondition: $(D_INLINECODE allocator is null).
|
||||||
*/
|
*/
|
||||||
this(S)(S init, shared Allocator allocator = defaultAllocator)
|
this(S)(S init, shared Allocator allocator = defaultAllocator) @trusted
|
||||||
nothrow @trusted @nogc
|
|
||||||
if (is(S == String))
|
if (is(S == String))
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
@ -417,8 +416,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
this(S)(ref S init, shared Allocator allocator = defaultAllocator)
|
this(S)(ref S init, shared Allocator allocator = defaultAllocator) @trusted
|
||||||
nothrow @trusted @nogc
|
|
||||||
if (is(Unqual!S == String))
|
if (is(Unqual!S == String))
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
@ -428,7 +426,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
this(shared Allocator allocator) pure nothrow @safe @nogc
|
this(shared Allocator allocator) @nogc nothrow pure @safe
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(allocator !is null);
|
assert(allocator !is null);
|
||||||
@ -478,7 +476,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto s = String(1, 'О');
|
auto s = String(1, 'О');
|
||||||
@ -494,13 +492,13 @@ struct String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String(0, 'K');
|
auto s = String(0, 'K');
|
||||||
assert(s.length == 0);
|
assert(s.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this(this) @nogc nothrow @trusted
|
this(this) @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
auto buf = this.data[0 .. this.length_];
|
auto buf = this.data[0 .. this.length_];
|
||||||
this.length_ = capacity_ = 0;
|
this.length_ = capacity_ = 0;
|
||||||
@ -511,13 +509,13 @@ struct String
|
|||||||
/**
|
/**
|
||||||
* Destroys the string.
|
* Destroys the string.
|
||||||
*/
|
*/
|
||||||
~this() nothrow @trusted @nogc
|
~this() @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
allocator.resize(this.data[0 .. this.capacity_], 0);
|
allocator.resize(this.data[0 .. this.capacity_], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write4Bytes(ref const dchar src)
|
private void write4Bytes(ref const dchar src)
|
||||||
pure nothrow @trusted @nogc
|
@nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(capacity - length >= 4);
|
assert(capacity - length >= 4);
|
||||||
@ -578,7 +576,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL UTFException).
|
* Throws: $(D_PSYMBOL UTFException).
|
||||||
*/
|
*/
|
||||||
size_t insertBack(const char chr) @trusted @nogc
|
size_t insertBack(const char chr) @nogc pure @trusted
|
||||||
{
|
{
|
||||||
if ((chr & 0x80) != 0)
|
if ((chr & 0x80) != 0)
|
||||||
{
|
{
|
||||||
@ -593,7 +591,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
size_t insertBack(const wchar chr) @trusted @nogc
|
size_t insertBack(const wchar chr) @nogc pure @trusted
|
||||||
{
|
{
|
||||||
reserve(length + 3);
|
reserve(length + 3);
|
||||||
|
|
||||||
@ -606,13 +604,13 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocates enough space for 3-byte character.
|
// Allocates enough space for 3-byte character.
|
||||||
private @safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
s.insertBack('\u8100');
|
s.insertBack('\u8100');
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
UTFException exception;
|
UTFException exception;
|
||||||
try
|
try
|
||||||
@ -628,7 +626,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
size_t insertBack(const dchar chr) @trusted @nogc
|
size_t insertBack(const dchar chr) @nogc pure @trusted
|
||||||
{
|
{
|
||||||
reserve(length + dchar.sizeof);
|
reserve(length + dchar.sizeof);
|
||||||
|
|
||||||
@ -648,7 +646,7 @@ struct String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
UTFException exception;
|
UTFException exception;
|
||||||
try
|
try
|
||||||
@ -835,7 +833,7 @@ struct String
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Desired size in bytes.
|
* size = Desired size in bytes.
|
||||||
*/
|
*/
|
||||||
void reserve(const size_t size) nothrow @trusted @nogc
|
void reserve(const size_t size) @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
if (this.capacity_ >= size)
|
if (this.capacity_ >= size)
|
||||||
{
|
{
|
||||||
@ -847,7 +845,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
assert(s.capacity == 0);
|
assert(s.capacity == 0);
|
||||||
@ -871,7 +869,7 @@ struct String
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Desired size.
|
* size = Desired size.
|
||||||
*/
|
*/
|
||||||
void shrink(const size_t size) nothrow @trusted @nogc
|
void shrink(const size_t size) @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
if (this.capacity_ <= size)
|
if (this.capacity_ <= size)
|
||||||
{
|
{
|
||||||
@ -888,7 +886,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Die Alten lasen laut.");
|
auto s = String("Die Alten lasen laut.");
|
||||||
assert(s.capacity == 21);
|
assert(s.capacity == 21);
|
||||||
@ -907,13 +905,13 @@ struct String
|
|||||||
/**
|
/**
|
||||||
* Returns: String capacity in bytes.
|
* Returns: String capacity in bytes.
|
||||||
*/
|
*/
|
||||||
@property size_t capacity() const pure nothrow @safe @nogc
|
@property size_t capacity() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this.capacity_;
|
return this.capacity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("In allem Schreiben ist Schamlosigkeit.");
|
auto s = String("In allem Schreiben ist Schamlosigkeit.");
|
||||||
assert(s.capacity == 38);
|
assert(s.capacity == 38);
|
||||||
@ -935,7 +933,7 @@ struct String
|
|||||||
*/
|
*/
|
||||||
ByCodeUnit!char opSliceAssign(R)(ByCodeUnit!R value,
|
ByCodeUnit!char opSliceAssign(R)(ByCodeUnit!R value,
|
||||||
const size_t i,
|
const size_t i,
|
||||||
const size_t j) @trusted
|
const size_t j)
|
||||||
if (is(Unqual!R == char))
|
if (is(Unqual!R == char))
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@ -954,7 +952,7 @@ struct String
|
|||||||
ByCodeUnit!char opSliceAssign(const char[] value,
|
ByCodeUnit!char opSliceAssign(const char[] value,
|
||||||
const size_t i,
|
const size_t i,
|
||||||
const size_t j)
|
const size_t j)
|
||||||
pure nothrow @trusted @nogc
|
@nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -970,7 +968,7 @@ struct String
|
|||||||
ByCodeUnit!char opSliceAssign(const char value,
|
ByCodeUnit!char opSliceAssign(const char value,
|
||||||
const size_t i,
|
const size_t i,
|
||||||
const size_t j)
|
const size_t j)
|
||||||
pure nothrow @trusted @nogc
|
@nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -992,13 +990,13 @@ struct String
|
|||||||
*
|
*
|
||||||
* Returns: The array representing the string.
|
* Returns: The array representing the string.
|
||||||
*/
|
*/
|
||||||
inout(char)[] get() inout pure nothrow @trusted @nogc
|
inout(char)[] get() inout @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
return this.data[0 .. this.length_];
|
return this.data[0 .. this.length_];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Char array.");
|
auto s = String("Char array.");
|
||||||
assert(s.get().length == 11);
|
assert(s.get().length == 11);
|
||||||
@ -1010,7 +1008,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Returns: Null-terminated string.
|
* Returns: Null-terminated string.
|
||||||
*/
|
*/
|
||||||
const(char)* toStringz() nothrow @nogc
|
const(char)* toStringz() @nogc nothrow pure
|
||||||
{
|
{
|
||||||
reserve(length + 1);
|
reserve(length + 1);
|
||||||
this.data[length] = '\0';
|
this.data[length] = '\0';
|
||||||
@ -1018,7 +1016,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc pure unittest
|
||||||
{
|
{
|
||||||
auto s = String("C string.");
|
auto s = String("C string.");
|
||||||
assert(s.toStringz()[0] == 'C');
|
assert(s.toStringz()[0] == 'C');
|
||||||
@ -1028,7 +1026,7 @@ struct String
|
|||||||
/**
|
/**
|
||||||
* Returns: The number of code units that are required to encode the string.
|
* Returns: The number of code units that are required to encode the string.
|
||||||
*/
|
*/
|
||||||
@property size_t length() const pure nothrow @safe @nogc
|
@property size_t length() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this.length_;
|
return this.length_;
|
||||||
}
|
}
|
||||||
@ -1037,7 +1035,7 @@ struct String
|
|||||||
alias opDollar = length;
|
alias opDollar = length;
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Piscis primuin a capite foetat.");
|
auto s = String("Piscis primuin a capite foetat.");
|
||||||
assert(s.length == 31);
|
assert(s.length == 31);
|
||||||
@ -1052,7 +1050,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE length > pos).
|
* Precondition: $(D_INLINECODE length > pos).
|
||||||
*/
|
*/
|
||||||
ref inout(char) opIndex(const size_t pos) inout pure nothrow @trusted @nogc
|
ref inout(char) opIndex(const size_t pos) inout @nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(length > pos);
|
assert(length > pos);
|
||||||
@ -1063,7 +1061,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Alea iacta est.");
|
auto s = String("Alea iacta est.");
|
||||||
assert(s[0] == 'A');
|
assert(s[0] == 'A');
|
||||||
@ -1074,7 +1072,7 @@ struct String
|
|||||||
* Returns: Random access range that iterates over the string by bytes, in
|
* Returns: Random access range that iterates over the string by bytes, in
|
||||||
* forward order.
|
* forward order.
|
||||||
*/
|
*/
|
||||||
ByCodeUnit!char opIndex() pure nothrow @trusted @nogc
|
ByCodeUnit!char opIndex() @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
return typeof(return)(this, this.data, this.data + length);
|
return typeof(return)(this, this.data, this.data + length);
|
||||||
}
|
}
|
||||||
@ -1086,7 +1084,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Plutarchus");
|
auto s = String("Plutarchus");
|
||||||
auto r = s[];
|
auto r = s[];
|
||||||
@ -1104,22 +1102,35 @@ struct String
|
|||||||
assert(r.length == 8);
|
assert(r.length == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc pure @safe unittest
|
||||||
|
{
|
||||||
|
auto s = const String("Was ich vermag, soll gern geschehen. Goethe");
|
||||||
|
auto r1 = s[];
|
||||||
|
assert(r1.front == 'W');
|
||||||
|
|
||||||
|
auto r2 = r1[];
|
||||||
|
r1.popFront();
|
||||||
|
assert(r1.front == 'a');
|
||||||
|
assert(r2.front == 'W');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: Forward range that iterates over the string by code points.
|
* Returns: Forward range that iterates over the string by code points.
|
||||||
*/
|
*/
|
||||||
ByCodePoint!char byCodePoint() pure nothrow @trusted @nogc
|
ByCodePoint!char byCodePoint() @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
return typeof(return)(this, this.data, this.data + length);
|
return typeof(return)(this, this.data, this.data + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ByCodePoint!(const char) byCodePoint() const pure nothrow @trusted @nogc
|
ByCodePoint!(const char) byCodePoint() const @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
return typeof(return)(this, this.data, this.data + length);
|
return typeof(return)(this, this.data, this.data + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Мне есть, что спеть, представ перед Всевышним.");
|
auto s = String("Мне есть, что спеть, представ перед Всевышним.");
|
||||||
auto cp = s.byCodePoint();
|
auto cp = s.byCodePoint();
|
||||||
@ -1139,7 +1150,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = const String("Высоцкий");
|
auto s = const String("Высоцкий");
|
||||||
auto cp1 = s.byCodePoint();
|
auto cp1 = s.byCodePoint();
|
||||||
@ -1157,15 +1168,18 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: $(D_KEYWORD true) if the string is empty.
|
* Returns whether the string is empty.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if the string is empty, $(D_KEYWORD false)
|
||||||
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
@property bool empty() const pure nothrow @safe @nogc
|
@property bool empty() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return length == 0;
|
return length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
assert(s.empty);
|
assert(s.empty);
|
||||||
@ -1185,7 +1199,7 @@ struct String
|
|||||||
* Precondition: $(D_INLINECODE i <= j && j <= length).
|
* Precondition: $(D_INLINECODE i <= j && j <= length).
|
||||||
*/
|
*/
|
||||||
ByCodeUnit!char opSlice(const size_t i, const size_t j)
|
ByCodeUnit!char opSlice(const size_t i, const size_t j)
|
||||||
pure nothrow @trusted @nogc
|
@nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -1198,7 +1212,7 @@ struct String
|
|||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ByCodeUnit!(const char) opSlice(const size_t i, const size_t j)
|
ByCodeUnit!(const char) opSlice(const size_t i, const size_t j)
|
||||||
const pure nothrow @trusted @nogc
|
const @nogc nothrow pure @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -1210,7 +1224,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Vladimir Soloviev");
|
auto s = String("Vladimir Soloviev");
|
||||||
auto r = s[9 .. $];
|
auto r = s[9 .. $];
|
||||||
@ -1274,7 +1288,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Черная, потом пропахшая выть!");
|
auto s = String("Черная, потом пропахшая выть!");
|
||||||
s = String("Как мне тебя не ласкать, не любить?");
|
s = String("Как мне тебя не ласкать, не любить?");
|
||||||
@ -1291,7 +1305,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL UTFException).
|
* Throws: $(D_PSYMBOL UTFException).
|
||||||
*/
|
*/
|
||||||
ref String opAssign(S)(S that) nothrow
|
ref String opAssign(S)(S that)
|
||||||
if (!isInfinite!S
|
if (!isInfinite!S
|
||||||
&& isInputRange!S
|
&& isInputRange!S
|
||||||
&& isSomeChar!(ElementType!S))
|
&& isSomeChar!(ElementType!S))
|
||||||
@ -1302,7 +1316,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Оловом светится лужная голь...");
|
auto s = String("Оловом светится лужная голь...");
|
||||||
s = "Грустная песня, ты - русская боль.";
|
s = "Грустная песня, ты - русская боль.";
|
||||||
@ -1347,7 +1361,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(String("Голубая кофта.") < String("Синие глаза."));
|
assert(String("Голубая кофта.") < String("Синие глаза."));
|
||||||
assert(String("Никакой я правды") < String("милой не сказал")[]);
|
assert(String("Никакой я правды") < String("милой не сказал")[]);
|
||||||
@ -1400,7 +1414,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(String("Милая спросила:") != String("Крутит ли метель?"));
|
assert(String("Милая спросила:") != String("Крутит ли метель?"));
|
||||||
assert(String("Затопить бы печку,") != String("постелить постель.")[]);
|
assert(String("Затопить бы печку,") != String("постелить постель.")[]);
|
||||||
@ -1427,13 +1441,13 @@ struct String
|
|||||||
* Precondition: $(D_INLINECODE length > pos).
|
* Precondition: $(D_INLINECODE length > pos).
|
||||||
*/
|
*/
|
||||||
ref char opIndexAssign(const char value, const size_t pos)
|
ref char opIndexAssign(const char value, const size_t pos)
|
||||||
pure nothrow @safe @nogc
|
@nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return opIndex(pos) = value;
|
return opIndex(pos) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("alea iacta est.");
|
auto s = String("alea iacta est.");
|
||||||
|
|
||||||
@ -1458,7 +1472,7 @@ struct String
|
|||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("Buttercup");
|
auto s1 = String("Buttercup");
|
||||||
auto s2 = String("Cap");
|
auto s2 = String("Cap");
|
||||||
@ -1467,12 +1481,12 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ByCodeUnit!char opIndexAssign(const char value) pure nothrow @safe @nogc
|
ByCodeUnit!char opIndexAssign(const char value) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("Wow");
|
auto s1 = String("Wow");
|
||||||
s1[] = 'a';
|
s1[] = 'a';
|
||||||
@ -1480,12 +1494,12 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ByCodeUnit!char opIndexAssign(const char[] value) pure nothrow @safe @nogc
|
ByCodeUnit!char opIndexAssign(const char[] value) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("ö");
|
auto s1 = String("ö");
|
||||||
s1[] = "oe";
|
s1[] = "oe";
|
||||||
@ -1521,7 +1535,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Из пословицы слова не выкинешь.");
|
auto s = String("Из пословицы слова не выкинешь.");
|
||||||
|
|
||||||
@ -1575,7 +1589,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Казнить нельзя помиловать.");
|
auto s = String("Казнить нельзя помиловать.");
|
||||||
s.insertAfter(s[0 .. 27], ",");
|
s.insertAfter(s[0 .. 27], ",");
|
||||||
@ -1604,7 +1618,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Казнить нельзя помиловать.");
|
auto s = String("Казнить нельзя помиловать.");
|
||||||
s.insertBefore(s[27 .. $], ",");
|
s.insertBefore(s[27 .. $], ",");
|
||||||
@ -1619,7 +1633,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Postblit works.
|
// Postblit works.
|
||||||
@nogc @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
void internFunc(String arg)
|
void internFunc(String arg)
|
||||||
{
|
{
|
||||||
|
235
source/tanya/conv.d
Normal file
235
source/tanya/conv.d
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module provides functions for converting between different types.
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/conv.d,
|
||||||
|
* tanya/conv.d)
|
||||||
|
*/
|
||||||
|
module tanya.conv;
|
||||||
|
|
||||||
|
import tanya.memory;
|
||||||
|
import tanya.memory.op;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new object of type $(D_PARAM T) in $(D_PARAM memory) with the
|
||||||
|
* given arguments.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM T) is a $(D_KEYWORD class), emplace returns a class reference
|
||||||
|
* of type $(D_PARAM T), otherwise a pointer to the constructed object is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM T) is a nested class inside another class, $(D_PARAM outer)
|
||||||
|
* should be an instance of the outer class.
|
||||||
|
*
|
||||||
|
* $(D_PARAM args) are arguments for the constructor of $(D_PARAM T). If
|
||||||
|
* $(D_PARAM T) isn't an aggregate type and doesn't have a constructor,
|
||||||
|
* $(D_PARAM memory) can be initialized to `args[0]` if `Args.length == 1`,
|
||||||
|
* `Args[0]` should be implicitly convertible to $(D_PARAM T) then.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Constructed type.
|
||||||
|
* U = Type of the outer class if $(D_PARAM T) is a nested class.
|
||||||
|
* Args = Types of the constructor arguments if $(D_PARAM T) has a constructor
|
||||||
|
* or the type of the initial value.
|
||||||
|
* outer = Outer class instance if $(D_PARAM T) is a nested class.
|
||||||
|
* args = Constructor arguments if $(D_PARAM T) has a constructor or the
|
||||||
|
* initial value.
|
||||||
|
*
|
||||||
|
* Returns: New instance of type $(D_PARAM T) constructed in $(D_PARAM memory).
|
||||||
|
*
|
||||||
|
* Precondition: `memory.length == stateSize!T`.
|
||||||
|
* Postcondition: $(D_PARAM memory) and the result point to the same memory.
|
||||||
|
*/
|
||||||
|
T emplace(T, U, Args...)(void[] memory, U outer, auto ref Args args)
|
||||||
|
if (!isAbstractClass!T && isInnerClass!T && is(typeof(T.outer) == U))
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(memory.length >= stateSize!T);
|
||||||
|
}
|
||||||
|
out (result)
|
||||||
|
{
|
||||||
|
assert(memory.ptr is (() @trusted => cast(void*) result)());
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
copy(typeid(T).initializer, memory);
|
||||||
|
|
||||||
|
auto result = (() @trusted => cast(T) memory.ptr)();
|
||||||
|
result.outer = outer;
|
||||||
|
|
||||||
|
static if (is(typeof(result.__ctor(args))))
|
||||||
|
{
|
||||||
|
result.__ctor(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
T emplace(T, Args...)(void[] memory, auto ref Args args)
|
||||||
|
if (is(T == class) && !isAbstractClass!T && !isInnerClass!T)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(memory.length == stateSize!T);
|
||||||
|
}
|
||||||
|
out (result)
|
||||||
|
{
|
||||||
|
assert(memory.ptr is (() @trusted => cast(void*) result)());
|
||||||
|
}body
|
||||||
|
{
|
||||||
|
copy(typeid(T).initializer, memory);
|
||||||
|
|
||||||
|
auto result = (() @trusted => cast(T) memory.ptr)();
|
||||||
|
static if (is(typeof(result.__ctor(args))))
|
||||||
|
{
|
||||||
|
result.__ctor(args);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
import tanya.memory : stateSize;
|
||||||
|
|
||||||
|
class C
|
||||||
|
{
|
||||||
|
int i = 5;
|
||||||
|
class Inner
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
this(int param) pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
this.i = param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ubyte[stateSize!C] memory1;
|
||||||
|
ubyte[stateSize!(C.Inner)] memory2;
|
||||||
|
|
||||||
|
auto c = emplace!C(memory1);
|
||||||
|
assert(c.i == 5);
|
||||||
|
|
||||||
|
auto inner = emplace!(C.Inner)(memory2, c, 8);
|
||||||
|
assert(c.i == 5);
|
||||||
|
assert(inner.i == 8);
|
||||||
|
assert(inner.outer is c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
T* emplace(T, Args...)(void[] memory, auto ref Args args)
|
||||||
|
if (!isAggregateType!T && (Args.length <= 1))
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(memory.length >= T.sizeof);
|
||||||
|
}
|
||||||
|
out (result)
|
||||||
|
{
|
||||||
|
assert(memory.ptr is result);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
auto result = (() @trusted => cast(T*) memory.ptr)();
|
||||||
|
static if (Args.length == 1)
|
||||||
|
{
|
||||||
|
*result = T(args[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*result = T.init;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
T* emplace(T, Args...)(void[] memory, auto ref Args args)
|
||||||
|
if (!isPolymorphicType!T && isAggregateType!T)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(memory.length >= T.sizeof);
|
||||||
|
}
|
||||||
|
out (result)
|
||||||
|
{
|
||||||
|
assert(memory.ptr is result);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
auto result = (() @trusted => cast(T*) memory.ptr)();
|
||||||
|
static if (!hasElaborateAssign!T && isAssignable!T)
|
||||||
|
{
|
||||||
|
*result = T.init;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const T init = T.init;
|
||||||
|
copy((cast(void*) &init)[0 .. T.sizeof], memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (Args.length == 0)
|
||||||
|
{
|
||||||
|
static assert(is(typeof({ static T t; })),
|
||||||
|
"Default constructor is disabled");
|
||||||
|
}
|
||||||
|
else static if (is(typeof(T(args))))
|
||||||
|
{
|
||||||
|
*result = T(args);
|
||||||
|
}
|
||||||
|
else static if (is(typeof(result.__ctor(args))))
|
||||||
|
{
|
||||||
|
result.__ctor(args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false,
|
||||||
|
"Unable to construct value with the given arguments");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte[4] memory;
|
||||||
|
|
||||||
|
auto i = emplace!int(memory);
|
||||||
|
static assert(is(typeof(i) == int*));
|
||||||
|
assert(*i == 0);
|
||||||
|
|
||||||
|
i = emplace!int(memory, 5);
|
||||||
|
assert(*i == 5);
|
||||||
|
|
||||||
|
static struct S
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
@disable this();
|
||||||
|
@disable this(this);
|
||||||
|
this(int i) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto s = emplace!S(memory, 8);
|
||||||
|
static assert(is(typeof(s) == S*));
|
||||||
|
assert(s.i == 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles "Cannot access frame pointer" error.
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
struct F
|
||||||
|
{
|
||||||
|
~this() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(is(typeof(emplace!F((void[]).init))));
|
||||||
|
}
|
66
source/tanya/exception.d
Normal file
66
source/tanya/exception.d
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common exceptions and errors.
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d,
|
||||||
|
* tanya/exception.d)
|
||||||
|
*/
|
||||||
|
module tanya.exception;
|
||||||
|
|
||||||
|
import tanya.conv;
|
||||||
|
import tanya.memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown if memory allocation fails.
|
||||||
|
*/
|
||||||
|
final class OutOfMemoryError : Error
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs new error.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* msg = The message for the exception.
|
||||||
|
* file = The file where the exception occurred.
|
||||||
|
* line = The line number where the exception occurred.
|
||||||
|
* next = The previous exception in the chain of exceptions, if any.
|
||||||
|
*/
|
||||||
|
this(string msg = "Out of memory",
|
||||||
|
string file = __FILE__,
|
||||||
|
size_t line = __LINE__,
|
||||||
|
Throwable next = null) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
super(msg, file, line, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
this(string msg,
|
||||||
|
Throwable next,
|
||||||
|
string file = __FILE__,
|
||||||
|
size_t line = __LINE__) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
super(msg, file, line, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates $(D_PSYMBOL OutOfMemoryError) in a static storage and throws it.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* msg = Custom error message.
|
||||||
|
*
|
||||||
|
* Throws: $(D_PSYMBOL OutOfMemoryError).
|
||||||
|
*/
|
||||||
|
void onOutOfMemoryError(string msg = "Out of memory")
|
||||||
|
@nogc nothrow pure @trusted
|
||||||
|
{
|
||||||
|
static ubyte[stateSize!OutOfMemoryError] memory;
|
||||||
|
alias PureType = OutOfMemoryError function(string) @nogc nothrow pure;
|
||||||
|
throw (cast(PureType) () => emplace!OutOfMemoryError(memory))(msg);
|
||||||
|
}
|
@ -14,10 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory;
|
module tanya.memory;
|
||||||
|
|
||||||
import core.exception;
|
|
||||||
import std.algorithm.iteration;
|
import std.algorithm.iteration;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import tanya.conv;
|
||||||
|
import tanya.exception;
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
import tanya.memory.mmappool;
|
import tanya.memory.mmappool;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
@ -229,14 +229,14 @@ package(tanya) T[] resize(T)(shared Allocator allocator,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
onOutOfMemoryErrorNoGC();
|
onOutOfMemoryError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void[] buf = array;
|
void[] buf = array;
|
||||||
if (!allocator.reallocate(buf, length * T.sizeof))
|
if (!allocator.reallocate(buf, length * T.sizeof))
|
||||||
{
|
{
|
||||||
onOutOfMemoryErrorNoGC();
|
onOutOfMemoryError();
|
||||||
}
|
}
|
||||||
// Casting from void[] is unsafe, but we know we cast to the original type.
|
// Casting from void[] is unsafe, but we know we cast to the original type.
|
||||||
array = cast(T[]) buf;
|
array = cast(T[]) buf;
|
||||||
@ -453,9 +453,7 @@ body
|
|||||||
{
|
{
|
||||||
() @trusted { allocator.deallocate(mem); }();
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
}
|
}
|
||||||
|
return emplace!T(mem[0 .. stateSize!T], args);
|
||||||
auto ptr = (() @trusted => (cast(T*) mem[0 .. stateSize!T].ptr))();
|
|
||||||
return emplace!T(ptr, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -6,7 +6,13 @@
|
|||||||
* Smart pointers.
|
* Smart pointers.
|
||||||
*
|
*
|
||||||
* A smart pointer is an object that wraps a raw pointer or a reference
|
* A smart pointer is an object that wraps a raw pointer or a reference
|
||||||
* (class, array) to manage its lifetime.
|
* (class, dynamic array) to manage its lifetime.
|
||||||
|
*
|
||||||
|
* This module provides two kinds of lifetime management strategies:
|
||||||
|
* $(UL
|
||||||
|
* $(LI Reference counting)
|
||||||
|
* $(LI Unique ownership)
|
||||||
|
* )
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2017.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
@ -17,17 +23,17 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory.smartref;
|
module tanya.memory.smartref;
|
||||||
|
|
||||||
import core.exception;
|
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import tanya.conv;
|
||||||
|
import tanya.exception;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.range.primitive;
|
import tanya.range.primitive;
|
||||||
|
|
||||||
private template Payload(T)
|
private template Payload(T)
|
||||||
{
|
{
|
||||||
static if (is(T == class) || is(T == interface) || isArray!T)
|
static if (isPolymorphicType!T || isArray!T)
|
||||||
{
|
{
|
||||||
alias Payload = T;
|
alias Payload = T;
|
||||||
}
|
}
|
||||||
@ -202,13 +208,6 @@ struct RefCounted(T)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
|
||||||
{
|
|
||||||
auto rc = defaultAllocator.refCounted!int(5);
|
|
||||||
rc = defaultAllocator.make!int(7);
|
|
||||||
assert(*rc == 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ref typeof(this) opAssign(typeof(null))
|
ref typeof(this) opAssign(typeof(null))
|
||||||
{
|
{
|
||||||
@ -229,14 +228,6 @@ struct RefCounted(T)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
|
||||||
{
|
|
||||||
RefCounted!int rc;
|
|
||||||
assert(!rc.isInitialized);
|
|
||||||
rc = null;
|
|
||||||
assert(!rc.isInitialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ref typeof(this) opAssign(typeof(this) rhs)
|
ref typeof(this) opAssign(typeof(this) rhs)
|
||||||
{
|
{
|
||||||
@ -308,7 +299,7 @@ struct RefCounted(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = RefCounted!int(defaultAllocator.make!int(5), defaultAllocator);
|
auto rc = RefCounted!int(defaultAllocator.make!int(5), defaultAllocator);
|
||||||
auto val = rc.get();
|
auto val = rc.get();
|
||||||
@ -324,7 +315,22 @@ unittest
|
|||||||
assert(*rc.storage.payload == 9);
|
assert(*rc.storage.payload == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
|
{
|
||||||
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
|
rc = defaultAllocator.make!int(7);
|
||||||
|
assert(*rc == 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc @system unittest
|
||||||
|
{
|
||||||
|
RefCounted!int rc;
|
||||||
|
assert(!rc.isInitialized);
|
||||||
|
rc = null;
|
||||||
|
assert(!rc.isInitialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.refCounted!int(5);
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
|
|
||||||
@ -340,7 +346,7 @@ private @nogc unittest
|
|||||||
assert(*rc == 5);
|
assert(*rc == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
RefCounted!int rc;
|
RefCounted!int rc;
|
||||||
|
|
||||||
@ -355,7 +361,7 @@ private @nogc unittest
|
|||||||
assert(rc.count == 0);
|
assert(rc.count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
RefCounted!int rc1, rc2;
|
RefCounted!int rc1, rc2;
|
||||||
static assert(is(typeof(rc1 = rc2)));
|
static assert(is(typeof(rc1 = rc2)));
|
||||||
@ -389,7 +395,7 @@ version (unittest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
uint destroyed;
|
uint destroyed;
|
||||||
auto a = defaultAllocator.make!A(destroyed);
|
auto a = defaultAllocator.make!A(destroyed);
|
||||||
@ -399,7 +405,7 @@ private @nogc unittest
|
|||||||
auto rc = RefCounted!A(a, defaultAllocator);
|
auto rc = RefCounted!A(a, defaultAllocator);
|
||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
|
|
||||||
void func(RefCounted!A rc) @nogc
|
void func(RefCounted!A rc) @nogc @system
|
||||||
{
|
{
|
||||||
assert(rc.count == 2);
|
assert(rc.count == 2);
|
||||||
}
|
}
|
||||||
@ -415,14 +421,14 @@ private @nogc unittest
|
|||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = RefCounted!int(defaultAllocator);
|
auto rc = RefCounted!int(defaultAllocator);
|
||||||
assert(!rc.isInitialized);
|
assert(!rc.isInitialized);
|
||||||
assert(rc.allocator is defaultAllocator);
|
assert(rc.allocator is defaultAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.refCounted!int(5);
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
@ -444,7 +450,7 @@ private @nogc unittest
|
|||||||
assert(rc.count == 0);
|
assert(rc.count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.refCounted!int(5);
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
assert(*rc == 5);
|
assert(*rc == 5);
|
||||||
@ -460,7 +466,7 @@ private unittest
|
|||||||
assert(*rc == 5);
|
assert(*rc == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static assert(is(typeof(RefCounted!int.storage.payload) == int*));
|
static assert(is(typeof(RefCounted!int.storage.payload) == int*));
|
||||||
static assert(is(typeof(RefCounted!A.storage.payload) == A));
|
static assert(is(typeof(RefCounted!A.storage.payload) == A));
|
||||||
@ -511,17 +517,9 @@ body
|
|||||||
{
|
{
|
||||||
() @trusted { allocator.deallocate(mem); }();
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
}
|
}
|
||||||
rc.storage = emplace!((RefCounted!T.Storage))(mem[0 .. storageSize]);
|
rc.storage = emplace!(RefCounted!T.Storage)(mem[0 .. storageSize]);
|
||||||
|
|
||||||
static if (is(T == class))
|
|
||||||
{
|
|
||||||
rc.storage.payload = emplace!T(mem[storageSize .. $], args);
|
rc.storage.payload = emplace!T(mem[storageSize .. $], args);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto ptr = (() @trusted => (cast(T*) mem[storageSize .. $].ptr))();
|
|
||||||
rc.storage.payload = emplace!T(ptr, args);
|
|
||||||
}
|
|
||||||
rc.deleter = &unifiedDeleter!(Payload!T);
|
rc.deleter = &unifiedDeleter!(Payload!T);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -554,7 +552,7 @@ body
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.refCounted!int(5);
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
@ -575,7 +573,7 @@ unittest
|
|||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
struct E
|
struct E
|
||||||
{
|
{
|
||||||
@ -597,13 +595,13 @@ private @nogc unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.refCounted!(int[])(5);
|
auto rc = defaultAllocator.refCounted!(int[])(5);
|
||||||
assert(rc.length == 5);
|
assert(rc.length == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
auto p1 = defaultAllocator.make!int(5);
|
auto p1 = defaultAllocator.make!int(5);
|
||||||
auto p2 = p1;
|
auto p2 = p1;
|
||||||
@ -611,13 +609,13 @@ private @nogc unittest
|
|||||||
assert(rc.get() is p2);
|
assert(rc.get() is p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
static bool destroyed = false;
|
static bool destroyed = false;
|
||||||
|
|
||||||
struct F
|
static struct F
|
||||||
{
|
{
|
||||||
~this() @nogc
|
~this() @nogc nothrow @safe
|
||||||
{
|
{
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
}
|
}
|
||||||
@ -723,7 +721,7 @@ struct Unique(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto rc = defaultAllocator.unique!int(5);
|
auto rc = defaultAllocator.unique!int(5);
|
||||||
rc = defaultAllocator.make!int(7);
|
rc = defaultAllocator.make!int(7);
|
||||||
@ -770,7 +768,7 @@ struct Unique(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
Unique!int u;
|
Unique!int u;
|
||||||
assert(!u.isInitialized);
|
assert(!u.isInitialized);
|
||||||
@ -789,7 +787,7 @@ struct Unique(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto u = defaultAllocator.unique!int(5);
|
auto u = defaultAllocator.unique!int(5);
|
||||||
assert(u.isInitialized);
|
assert(u.isInitialized);
|
||||||
@ -804,7 +802,7 @@ struct Unique(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto p = defaultAllocator.make!int(5);
|
auto p = defaultAllocator.make!int(5);
|
||||||
auto s = Unique!int(p, defaultAllocator);
|
auto s = Unique!int(p, defaultAllocator);
|
||||||
@ -812,13 +810,13 @@ struct Unique(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow @system unittest
|
||||||
{
|
{
|
||||||
static bool destroyed = false;
|
static bool destroyed = false;
|
||||||
|
|
||||||
struct F
|
static struct F
|
||||||
{
|
{
|
||||||
~this() @nogc
|
~this() @nogc nothrow @safe
|
||||||
{
|
{
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
}
|
}
|
||||||
@ -885,13 +883,13 @@ body
|
|||||||
return Unique!T(payload, allocator);
|
return Unique!T(payload, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static assert(is(typeof(defaultAllocator.unique!B(5))));
|
static assert(is(typeof(defaultAllocator.unique!B(5))));
|
||||||
static assert(is(typeof(defaultAllocator.unique!(int[])(5))));
|
static assert(is(typeof(defaultAllocator.unique!(int[])(5))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto s = defaultAllocator.unique!int(5);
|
auto s = defaultAllocator.unique!int(5);
|
||||||
assert(*s == 5);
|
assert(*s == 5);
|
||||||
@ -900,7 +898,7 @@ private unittest
|
|||||||
assert(s is null);
|
assert(s is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto s = defaultAllocator.unique!int(5);
|
auto s = defaultAllocator.unique!int(5);
|
||||||
assert(*s == 5);
|
assert(*s == 5);
|
||||||
@ -909,7 +907,7 @@ private unittest
|
|||||||
assert(*s == 4);
|
assert(*s == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto p1 = defaultAllocator.make!int(5);
|
auto p1 = defaultAllocator.make!int(5);
|
||||||
auto p2 = p1;
|
auto p2 = p1;
|
||||||
@ -918,7 +916,7 @@ private @nogc unittest
|
|||||||
assert(rc.get() is p2);
|
assert(rc.get() is p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto rc = Unique!int(defaultAllocator);
|
auto rc = Unique!int(defaultAllocator);
|
||||||
assert(rc.allocator is defaultAllocator);
|
assert(rc.allocator is defaultAllocator);
|
||||||
|
Loading…
Reference in New Issue
Block a user