Implement pure onOutOfMemory
This commit is contained in:
		| @@ -27,7 +27,10 @@ Tanya consists of the following packages and (top-level) modules: | ||||
| * `async`: Event loop (epoll, kqueue and IOCP). | ||||
| * `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8 | ||||
| string, Hash set. | ||||
| * `conv`: This module provides functions for converting between different | ||||
| types. | ||||
| * `encoding`: This package provides tools to work with text encodings. | ||||
| * `exception`: Common exceptions and errors. | ||||
| * `format`: Formatting and conversion functions. | ||||
| * `math`: Arbitrary precision integer and a set of functions. | ||||
| * `memory`: Tools for manual memory management (allocators, smart pointers). | ||||
|   | ||||
| @@ -15,11 +15,10 @@ | ||||
| module tanya.container.array; | ||||
|  | ||||
| import core.checkedint; | ||||
| import core.exception; | ||||
| import std.algorithm.comparison; | ||||
| import std.algorithm.mutation; | ||||
| import std.conv; | ||||
| import std.meta; | ||||
| import tanya.exception; | ||||
| import tanya.memory; | ||||
| import tanya.meta.trait; | ||||
| import tanya.meta.transform; | ||||
| @@ -501,7 +500,7 @@ struct Array(T) | ||||
|             buf = allocator.allocate(byteSize); | ||||
|             if (buf is null) | ||||
|             { | ||||
|                 onOutOfMemoryErrorNoGC(); | ||||
|                 onOutOfMemoryError(); | ||||
|             } | ||||
|             scope (failure) | ||||
|             { | ||||
| @@ -708,9 +707,12 @@ struct Array(T) | ||||
|     size_t insertBack(R)(ref R el) @trusted | ||||
|         if (isImplicitlyConvertible!(R, T)) | ||||
|     { | ||||
|         reserve(this.length_ + 1); | ||||
|         emplace(this.data + this.length_, el); | ||||
|         ++this.length_; | ||||
|         this.length = this.length + 1; | ||||
|         scope (failure) | ||||
|         { | ||||
|             this.length = this.length - 1; | ||||
|         } | ||||
|         opIndex(this.length - 1) = el; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -14,9 +14,9 @@ | ||||
|  */ | ||||
| module tanya.container.queue; | ||||
|  | ||||
| import core.exception; | ||||
| import std.algorithm.mutation; | ||||
| import tanya.container.entry; | ||||
| import tanya.exception; | ||||
| import tanya.memory; | ||||
| import tanya.meta.trait; | ||||
|  | ||||
|   | ||||
| @@ -361,14 +361,14 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("\u10437"w); | ||||
|         assert(s == "\u10437"); | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Отказаться от вина - в этом страшная вина."d); | ||||
|         assert(s == "Отказаться от вина - в этом страшная вина."); | ||||
| @@ -392,8 +392,7 @@ struct String | ||||
|      * | ||||
|      * Precondition: $(D_INLINECODE allocator is null). | ||||
|      */ | ||||
|     this(S)(S init, shared Allocator allocator = defaultAllocator) | ||||
|     nothrow @trusted @nogc | ||||
|     this(S)(S init, shared Allocator allocator = defaultAllocator) @trusted | ||||
|     if (is(S == String)) | ||||
|     { | ||||
|         this(allocator); | ||||
| @@ -417,8 +416,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     this(S)(ref S init, shared Allocator allocator = defaultAllocator) | ||||
|     nothrow @trusted @nogc | ||||
|     this(S)(ref S init, shared Allocator allocator = defaultAllocator) @trusted | ||||
|     if (is(Unqual!S == String)) | ||||
|     { | ||||
|         this(allocator); | ||||
| @@ -428,7 +426,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     this(shared Allocator allocator) pure nothrow @safe @nogc | ||||
|     this(shared Allocator allocator) @nogc nothrow pure @safe | ||||
|     in | ||||
|     { | ||||
|         assert(allocator !is null); | ||||
| @@ -478,7 +476,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         { | ||||
|             auto s = String(1, 'О'); | ||||
| @@ -494,13 +492,13 @@ struct String | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String(0, 'K'); | ||||
|         assert(s.length == 0); | ||||
|     } | ||||
|  | ||||
|     this(this) @nogc nothrow @trusted | ||||
|     this(this) @nogc nothrow pure @trusted | ||||
|     { | ||||
|         auto buf = this.data[0 .. this.length_]; | ||||
|         this.length_ = capacity_ = 0; | ||||
| @@ -511,13 +509,13 @@ struct String | ||||
|     /** | ||||
|      * Destroys the string. | ||||
|      */ | ||||
|     ~this() nothrow @trusted @nogc | ||||
|     ~this() @nogc nothrow pure @trusted | ||||
|     { | ||||
|         allocator.resize(this.data[0 .. this.capacity_], 0); | ||||
|     } | ||||
|  | ||||
|     private void write4Bytes(ref const dchar src) | ||||
|     pure nothrow @trusted @nogc | ||||
|     @nogc nothrow pure @trusted | ||||
|     in | ||||
|     { | ||||
|         assert(capacity - length >= 4); | ||||
| @@ -578,7 +576,7 @@ struct String | ||||
|      * | ||||
|      * 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) | ||||
|         { | ||||
| @@ -593,7 +591,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     size_t insertBack(const wchar chr) @trusted @nogc | ||||
|     size_t insertBack(const wchar chr) @nogc pure @trusted | ||||
|     { | ||||
|         reserve(length + 3); | ||||
|  | ||||
| @@ -606,13 +604,13 @@ struct String | ||||
|     } | ||||
|  | ||||
|     // Allocates enough space for 3-byte character. | ||||
|     private @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         String s; | ||||
|         s.insertBack('\u8100'); | ||||
|     } | ||||
|  | ||||
|     private @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         UTFException exception; | ||||
|         try | ||||
| @@ -628,7 +626,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     size_t insertBack(const dchar chr) @trusted @nogc | ||||
|     size_t insertBack(const dchar chr) @nogc pure @trusted | ||||
|     { | ||||
|         reserve(length + dchar.sizeof); | ||||
|  | ||||
| @@ -648,7 +646,7 @@ struct String | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         UTFException exception; | ||||
|         try | ||||
| @@ -835,7 +833,7 @@ struct String | ||||
|      * Params: | ||||
|      *  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) | ||||
|         { | ||||
| @@ -847,7 +845,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc @safe unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         String s; | ||||
|         assert(s.capacity == 0); | ||||
| @@ -871,7 +869,7 @@ struct String | ||||
|      * Params: | ||||
|      *  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) | ||||
|         { | ||||
| @@ -888,7 +886,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc @safe unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Die Alten lasen laut."); | ||||
|         assert(s.capacity == 21); | ||||
| @@ -907,13 +905,13 @@ struct String | ||||
|     /** | ||||
|      * 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_; | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("In allem Schreiben ist Schamlosigkeit."); | ||||
|         assert(s.capacity == 38); | ||||
| @@ -935,7 +933,7 @@ struct String | ||||
|      */ | ||||
|     ByCodeUnit!char opSliceAssign(R)(ByCodeUnit!R value, | ||||
|                                      const size_t i, | ||||
|                                      const size_t j) @trusted | ||||
|                                      const size_t j) | ||||
|     if (is(Unqual!R == char)) | ||||
|     in | ||||
|     { | ||||
| @@ -954,7 +952,7 @@ struct String | ||||
|     ByCodeUnit!char opSliceAssign(const char[] value, | ||||
|                                   const size_t i, | ||||
|                                   const size_t j) | ||||
|     pure nothrow @trusted @nogc | ||||
|     @nogc nothrow pure @trusted | ||||
|     in | ||||
|     { | ||||
|         assert(i <= j); | ||||
| @@ -970,7 +968,7 @@ struct String | ||||
|     ByCodeUnit!char opSliceAssign(const char value, | ||||
|                                   const size_t i, | ||||
|                                   const size_t j) | ||||
|     pure nothrow @trusted @nogc | ||||
|     @nogc nothrow pure @trusted | ||||
|     in | ||||
|     { | ||||
|         assert(i <= j); | ||||
| @@ -992,13 +990,13 @@ struct 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_]; | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     nothrow @safe @nogc unittest | ||||
|     @nogc nothrow pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Char array."); | ||||
|         assert(s.get().length == 11); | ||||
| @@ -1010,7 +1008,7 @@ struct String | ||||
|      * | ||||
|      * Returns: Null-terminated string. | ||||
|      */ | ||||
|     const(char)* toStringz() nothrow @nogc | ||||
|     const(char)* toStringz() @nogc nothrow pure | ||||
|     { | ||||
|         reserve(length + 1); | ||||
|         this.data[length] = '\0'; | ||||
| @@ -1018,7 +1016,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc unittest | ||||
|     @nogc pure unittest | ||||
|     { | ||||
|         auto s = String("C string."); | ||||
|         assert(s.toStringz()[0] == 'C'); | ||||
| @@ -1028,7 +1026,7 @@ struct 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_; | ||||
|     } | ||||
| @@ -1037,7 +1035,7 @@ struct String | ||||
|     alias opDollar = length; | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Piscis primuin a capite foetat."); | ||||
|         assert(s.length == 31); | ||||
| @@ -1052,7 +1050,7 @@ struct String | ||||
|      * | ||||
|      * 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 | ||||
|     { | ||||
|         assert(length > pos); | ||||
| @@ -1063,7 +1061,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Alea iacta est."); | ||||
|         assert(s[0] == 'A'); | ||||
| @@ -1074,7 +1072,7 @@ struct String | ||||
|      * Returns: Random access range that iterates over the string by bytes, in | ||||
|      *          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); | ||||
|     } | ||||
| @@ -1086,7 +1084,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Plutarchus"); | ||||
|         auto r = s[]; | ||||
| @@ -1104,22 +1102,35 @@ struct String | ||||
|         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. | ||||
|      */ | ||||
|     ByCodePoint!char byCodePoint() pure nothrow @trusted @nogc | ||||
|     ByCodePoint!char byCodePoint() @nogc nothrow pure @trusted | ||||
|     { | ||||
|         return typeof(return)(this, this.data, this.data + length); | ||||
|     } | ||||
|  | ||||
|     /// 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); | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc @safe unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Мне есть, что спеть, представ перед Всевышним."); | ||||
|         auto cp = s.byCodePoint(); | ||||
| @@ -1139,7 +1150,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc @safe unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = const String("Высоцкий"); | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         String s; | ||||
|         assert(s.empty); | ||||
| @@ -1185,7 +1199,7 @@ struct String | ||||
|      * Precondition: $(D_INLINECODE i <= j && j <= length). | ||||
|      */ | ||||
|     ByCodeUnit!char opSlice(const size_t i, const size_t j) | ||||
|     pure nothrow @trusted @nogc | ||||
|     @nogc nothrow pure @trusted | ||||
|     in | ||||
|     { | ||||
|         assert(i <= j); | ||||
| @@ -1198,7 +1212,7 @@ struct String | ||||
|  | ||||
|     /// ditto | ||||
|     ByCodeUnit!(const char) opSlice(const size_t i, const size_t j) | ||||
|     const pure nothrow @trusted @nogc | ||||
|     const @nogc nothrow pure @trusted | ||||
|     in | ||||
|     { | ||||
|         assert(i <= j); | ||||
| @@ -1210,7 +1224,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Vladimir Soloviev"); | ||||
|         auto r = s[9 .. $]; | ||||
| @@ -1274,7 +1288,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Черная, потом пропахшая выть!"); | ||||
|         s = String("Как мне тебя не ласкать, не любить?"); | ||||
| @@ -1291,7 +1305,7 @@ struct String | ||||
|      * | ||||
|      * Throws: $(D_PSYMBOL UTFException). | ||||
|      */ | ||||
|     ref String opAssign(S)(S that) nothrow | ||||
|     ref String opAssign(S)(S that) | ||||
|     if (!isInfinite!S | ||||
|      && isInputRange!S | ||||
|      && isSomeChar!(ElementType!S)) | ||||
| @@ -1302,7 +1316,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Оловом светится лужная голь..."); | ||||
|         s = "Грустная песня, ты - русская боль."; | ||||
| @@ -1347,7 +1361,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         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("постелить постель.")[]); | ||||
| @@ -1427,13 +1441,13 @@ struct String | ||||
|      * Precondition: $(D_INLINECODE length > pos). | ||||
|      */ | ||||
|     ref char opIndexAssign(const char value, const size_t pos) | ||||
|     pure nothrow @safe @nogc | ||||
|     @nogc nothrow pure @safe | ||||
|     { | ||||
|         return opIndex(pos) = value; | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("alea iacta est."); | ||||
|  | ||||
| @@ -1458,7 +1472,7 @@ struct String | ||||
|         return opSliceAssign(value, 0, length); | ||||
|     } | ||||
|  | ||||
|     private unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s1 = String("Buttercup"); | ||||
|         auto s2 = String("Cap"); | ||||
| @@ -1467,12 +1481,12 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// 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); | ||||
|     } | ||||
|  | ||||
|     private unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s1 = String("Wow"); | ||||
|         s1[] = 'a'; | ||||
| @@ -1480,12 +1494,12 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// 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); | ||||
|     } | ||||
|  | ||||
|     private unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s1 = String("ö"); | ||||
|         s1[] = "oe"; | ||||
| @@ -1521,7 +1535,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc @safe unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Из пословицы слова не выкинешь."); | ||||
|  | ||||
| @@ -1575,7 +1589,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Казнить нельзя помиловать."); | ||||
|         s.insertAfter(s[0 .. 27], ","); | ||||
| @@ -1604,7 +1618,7 @@ struct String | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @safe @nogc unittest | ||||
|     @nogc pure @safe unittest | ||||
|     { | ||||
|         auto s = String("Казнить нельзя помиловать."); | ||||
|         s.insertBefore(s[27 .. $], ","); | ||||
| @@ -1619,7 +1633,7 @@ struct String | ||||
| } | ||||
|  | ||||
| // Postblit works. | ||||
| @nogc @safe unittest | ||||
| @nogc pure @safe unittest | ||||
| { | ||||
|     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; | ||||
|  | ||||
| import core.exception; | ||||
| import std.algorithm.iteration; | ||||
| import std.algorithm.mutation; | ||||
| import std.conv; | ||||
| import tanya.conv; | ||||
| import tanya.exception; | ||||
| public import tanya.memory.allocator; | ||||
| import tanya.memory.mmappool; | ||||
| import tanya.meta.trait; | ||||
| @@ -229,14 +229,14 @@ package(tanya) T[] resize(T)(shared Allocator allocator, | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             onOutOfMemoryErrorNoGC(); | ||||
|             onOutOfMemoryError(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void[] buf = array; | ||||
|     if (!allocator.reallocate(buf, length * T.sizeof)) | ||||
|     { | ||||
|         onOutOfMemoryErrorNoGC(); | ||||
|         onOutOfMemoryError(); | ||||
|     } | ||||
|     // Casting from void[] is unsafe, but we know we cast to the original type. | ||||
|     array = cast(T[]) buf; | ||||
| @@ -453,9 +453,7 @@ body | ||||
|     { | ||||
|         () @trusted { allocator.deallocate(mem); }(); | ||||
|     } | ||||
|  | ||||
|     auto ptr = (() @trusted => (cast(T*) mem[0 .. stateSize!T].ptr))(); | ||||
|     return emplace!T(ptr, args); | ||||
|     return emplace!T(mem[0 .. stateSize!T], args); | ||||
| } | ||||
|  | ||||
| /// | ||||
|   | ||||
| @@ -6,7 +6,13 @@ | ||||
|  * Smart pointers. | ||||
|  * | ||||
|  * 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. | ||||
|  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, | ||||
| @@ -17,17 +23,17 @@ | ||||
|  */ | ||||
| module tanya.memory.smartref; | ||||
|  | ||||
| import core.exception; | ||||
| import std.algorithm.comparison; | ||||
| import std.algorithm.mutation; | ||||
| import std.conv; | ||||
| import tanya.conv; | ||||
| import tanya.exception; | ||||
| import tanya.memory; | ||||
| import tanya.meta.trait; | ||||
| import tanya.range.primitive; | ||||
|  | ||||
| private template Payload(T) | ||||
| { | ||||
|     static if (is(T == class) || is(T == interface) || isArray!T) | ||||
|     static if (isPolymorphicType!T || isArray!T) | ||||
|     { | ||||
|         alias Payload = T; | ||||
|     } | ||||
| @@ -202,13 +208,6 @@ struct RefCounted(T) | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     private @nogc unittest | ||||
|     { | ||||
|         auto rc = defaultAllocator.refCounted!int(5); | ||||
|         rc = defaultAllocator.make!int(7); | ||||
|         assert(*rc == 7); | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     ref typeof(this) opAssign(typeof(null)) | ||||
|     { | ||||
| @@ -229,14 +228,6 @@ struct RefCounted(T) | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     private @nogc unittest | ||||
|     { | ||||
|         RefCounted!int rc; | ||||
|         assert(!rc.isInitialized); | ||||
|         rc = null; | ||||
|         assert(!rc.isInitialized); | ||||
|     } | ||||
|  | ||||
|     /// ditto | ||||
|     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 val = rc.get(); | ||||
| @@ -324,7 +315,22 @@ unittest | ||||
|     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); | ||||
|  | ||||
| @@ -340,7 +346,7 @@ private @nogc unittest | ||||
|     assert(*rc == 5); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     RefCounted!int rc; | ||||
|  | ||||
| @@ -355,7 +361,7 @@ private @nogc unittest | ||||
|     assert(rc.count == 0); | ||||
| } | ||||
|  | ||||
| private unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     RefCounted!int rc1, rc2; | ||||
|     static assert(is(typeof(rc1 = rc2))); | ||||
| @@ -389,7 +395,7 @@ version (unittest) | ||||
|     } | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     uint destroyed; | ||||
|     auto a = defaultAllocator.make!A(destroyed); | ||||
| @@ -399,7 +405,7 @@ private @nogc unittest | ||||
|         auto rc = RefCounted!A(a, defaultAllocator); | ||||
|         assert(rc.count == 1); | ||||
|  | ||||
|         void func(RefCounted!A rc) @nogc | ||||
|         void func(RefCounted!A rc) @nogc @system | ||||
|         { | ||||
|             assert(rc.count == 2); | ||||
|         } | ||||
| @@ -415,14 +421,14 @@ private @nogc unittest | ||||
|     assert(rc.count == 1); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto rc = RefCounted!int(defaultAllocator); | ||||
|     assert(!rc.isInitialized); | ||||
|     assert(rc.allocator is defaultAllocator); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto rc = defaultAllocator.refCounted!int(5); | ||||
|     assert(rc.count == 1); | ||||
| @@ -444,7 +450,7 @@ private @nogc unittest | ||||
|     assert(rc.count == 0); | ||||
| } | ||||
|  | ||||
| private unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto rc = defaultAllocator.refCounted!int(5); | ||||
|     assert(*rc == 5); | ||||
| @@ -460,7 +466,7 @@ private unittest | ||||
|     assert(*rc == 5); | ||||
| } | ||||
|  | ||||
| private unittest | ||||
| @nogc nothrow pure @safe unittest | ||||
| { | ||||
|     static assert(is(typeof(RefCounted!int.storage.payload) == int*)); | ||||
|     static assert(is(typeof(RefCounted!A.storage.payload) == A)); | ||||
| @@ -511,17 +517,9 @@ body | ||||
|     { | ||||
|         () @trusted { allocator.deallocate(mem); }(); | ||||
|     } | ||||
|     rc.storage = emplace!((RefCounted!T.Storage))(mem[0 .. storageSize]); | ||||
|     rc.storage = emplace!(RefCounted!T.Storage)(mem[0 .. storageSize]); | ||||
|     rc.storage.payload = emplace!T(mem[storageSize .. $], args); | ||||
|  | ||||
|     static if (is(T == class)) | ||||
|     { | ||||
|         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); | ||||
|     return rc; | ||||
| } | ||||
| @@ -554,7 +552,7 @@ body | ||||
| } | ||||
|  | ||||
| /// | ||||
| unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto rc = defaultAllocator.refCounted!int(5); | ||||
|     assert(rc.count == 1); | ||||
| @@ -575,7 +573,7 @@ unittest | ||||
|     assert(rc.count == 1); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     struct E | ||||
|     { | ||||
| @@ -597,13 +595,13 @@ private @nogc unittest | ||||
|     } | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto rc = defaultAllocator.refCounted!(int[])(5); | ||||
|     assert(rc.length == 5); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     auto p1 = defaultAllocator.make!int(5); | ||||
|     auto p2 = p1; | ||||
| @@ -611,13 +609,13 @@ private @nogc unittest | ||||
|     assert(rc.get() is p2); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc @system unittest | ||||
| { | ||||
|     static bool destroyed = false; | ||||
|  | ||||
|     struct F | ||||
|     static struct F | ||||
|     { | ||||
|         ~this() @nogc | ||||
|         ~this() @nogc nothrow @safe | ||||
|         { | ||||
|             destroyed = true; | ||||
|         } | ||||
| @@ -723,7 +721,7 @@ struct Unique(T) | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc unittest | ||||
|     @nogc nothrow pure @system unittest | ||||
|     { | ||||
|         auto rc = defaultAllocator.unique!int(5); | ||||
|         rc = defaultAllocator.make!int(7); | ||||
| @@ -770,7 +768,7 @@ struct Unique(T) | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc unittest | ||||
|     @nogc nothrow pure @system unittest | ||||
|     { | ||||
|         Unique!int u; | ||||
|         assert(!u.isInitialized); | ||||
| @@ -789,7 +787,7 @@ struct Unique(T) | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|     @nogc unittest | ||||
|     @nogc nothrow pure @system unittest | ||||
|     { | ||||
|         auto u = defaultAllocator.unique!int(5); | ||||
|         assert(u.isInitialized); | ||||
| @@ -804,7 +802,7 @@ struct Unique(T) | ||||
| } | ||||
|  | ||||
| /// | ||||
| @nogc unittest | ||||
| @nogc nothrow pure @system unittest | ||||
| { | ||||
|     auto p = defaultAllocator.make!int(5); | ||||
|     auto s = Unique!int(p, defaultAllocator); | ||||
| @@ -812,13 +810,13 @@ struct Unique(T) | ||||
| } | ||||
|  | ||||
| /// | ||||
| @nogc unittest | ||||
| @nogc nothrow @system unittest | ||||
| { | ||||
|     static bool destroyed = false; | ||||
|  | ||||
|     struct F | ||||
|     static struct F | ||||
|     { | ||||
|         ~this() @nogc | ||||
|         ~this() @nogc nothrow @safe | ||||
|         { | ||||
|             destroyed = true; | ||||
|         } | ||||
| @@ -885,13 +883,13 @@ body | ||||
|     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!(int[])(5)))); | ||||
| } | ||||
|  | ||||
| private unittest | ||||
| @nogc nothrow pure @system unittest | ||||
| { | ||||
|     auto s = defaultAllocator.unique!int(5); | ||||
|     assert(*s == 5); | ||||
| @@ -900,7 +898,7 @@ private unittest | ||||
|     assert(s is null); | ||||
| } | ||||
|  | ||||
| private unittest | ||||
| @nogc nothrow pure @system unittest | ||||
| { | ||||
|     auto s = defaultAllocator.unique!int(5); | ||||
|     assert(*s == 5); | ||||
| @@ -909,7 +907,7 @@ private unittest | ||||
|     assert(*s == 4); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc nothrow pure @system unittest | ||||
| { | ||||
|     auto p1 = defaultAllocator.make!int(5); | ||||
|     auto p2 = p1; | ||||
| @@ -918,7 +916,7 @@ private @nogc unittest | ||||
|     assert(rc.get() is p2); | ||||
| } | ||||
|  | ||||
| private @nogc unittest | ||||
| @nogc nothrow pure @system unittest | ||||
| { | ||||
|     auto rc = Unique!int(defaultAllocator); | ||||
|     assert(rc.allocator is defaultAllocator); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user