Move memory exception into memory.lifecycle
This commit is contained in:
parent
b458c6a380
commit
85d7a2b9ca
@ -31,7 +31,6 @@ string, Set, Hash table.
|
|||||||
* `conv`: This module provides functions for converting between different
|
* `conv`: This module provides functions for converting between different
|
||||||
types.
|
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.
|
||||||
* `functional`: Functions that manipulate other functions and their argument
|
* `functional`: Functions that manipulate other functions and their argument
|
||||||
lists.
|
lists.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Single-dimensioned array.
|
* Single-dimensioned array.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -17,7 +17,6 @@ module tanya.container.array;
|
|||||||
import core.checkedint;
|
import core.checkedint;
|
||||||
import tanya.algorithm.comparison;
|
import tanya.algorithm.comparison;
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.exception;
|
|
||||||
import tanya.functional;
|
import tanya.functional;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* This module contains buffers designed for C-style input/output APIs.
|
* This module contains buffers designed for C-style input/output APIs.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* Internal package used by containers that rely on entries/nodes.
|
* Internal package used by containers that rely on entries/nodes.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Hash table.
|
* Hash table.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2018.
|
* Copyright: Eugene Wissner 2018-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* This module contains singly-linked ($(D_PSYMBOL SList)) and doubly-linked
|
* This module contains singly-linked ($(D_PSYMBOL SList)) and doubly-linked
|
||||||
* ($(D_PSYMBOL DList)) lists.
|
* ($(D_PSYMBOL DList)) lists.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Abstract data types whose instances are collections of other objects.
|
* Abstract data types whose instances are collections of other objects.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* This module implements a $(D_PSYMBOL Set) container that stores unique
|
* This module implements a $(D_PSYMBOL Set) container that stores unique
|
||||||
* values without any particular order.
|
* values without any particular order.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017-2018.
|
* Copyright: Eugene Wissner 2017-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* Internally $(D_PSYMBOL String) is represented by a sequence of
|
* Internally $(D_PSYMBOL String) is represented by a sequence of
|
||||||
* $(D_KEYWORD char)s.
|
* $(D_KEYWORD char)s.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017-2018.
|
* Copyright: Eugene Wissner 2017-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -2,65 +2,15 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Common exceptions and errors.
|
* Copyright: Eugene Wissner 2017-2019.
|
||||||
*
|
|
||||||
* Copyright: Eugene Wissner 2017-2018.
|
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d,
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d,
|
||||||
* tanya/exception.d)
|
* tanya/exception.d)
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use tanya.memory.lifecycle instead")
|
||||||
module tanya.exception;
|
module tanya.exception;
|
||||||
|
|
||||||
import tanya.conv;
|
public import tanya.memory.lifecycle : onOutOfMemoryError, OutOfMemoryError;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Allocators are classes encapsulating memory allocation strategy. This allows
|
* Allocators are classes encapsulating memory allocation strategy. This allows
|
||||||
* to decouple memory management from the algorithms and the data.
|
* to decouple memory management from the algorithms and the data.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
360
source/tanya/memory/lifecycle.d
Normal file
360
source/tanya/memory/lifecycle.d
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle management functions, types and related exceptions.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2019.
|
||||||
|
* 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/memory/init.d,
|
||||||
|
* tanya/memory/init.d)
|
||||||
|
*/
|
||||||
|
module tanya.memory.lifecycle;
|
||||||
|
|
||||||
|
import tanya.algorithm.mutation;
|
||||||
|
import tanya.conv;
|
||||||
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.range.primitive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From druntime
|
||||||
|
extern (C)
|
||||||
|
private void _d_monitordelete(Object h, bool det) @nogc nothrow pure;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function used to create, resize or destroy a dynamic array. It
|
||||||
|
* may throw $(D_PSYMBOL OutOfMemoryError). The new
|
||||||
|
* allocated part of the array isn't initialized. This function can be trusted
|
||||||
|
* only in the data structures that can ensure that the array is
|
||||||
|
* allocated/rellocated/deallocated with the same allocator.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of the array being created.
|
||||||
|
* allocator = The allocator used for getting memory.
|
||||||
|
* array = A reference to the array being changed.
|
||||||
|
* length = New array length.
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM array).
|
||||||
|
*/
|
||||||
|
package(tanya) T[] resize(T)(shared Allocator allocator,
|
||||||
|
auto ref T[] array,
|
||||||
|
const size_t length) @trusted
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
if (allocator.deallocate(array))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
onOutOfMemoryError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void[] buf = array;
|
||||||
|
if (!allocator.reallocate(buf, length * T.sizeof))
|
||||||
|
{
|
||||||
|
onOutOfMemoryError();
|
||||||
|
}
|
||||||
|
// Casting from void[] is unsafe, but we know we cast to the original type.
|
||||||
|
array = cast(T[]) buf;
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
int[] p;
|
||||||
|
|
||||||
|
p = defaultAllocator.resize(p, 20);
|
||||||
|
assert(p.length == 20);
|
||||||
|
|
||||||
|
p = defaultAllocator.resize(p, 30);
|
||||||
|
assert(p.length == 30);
|
||||||
|
|
||||||
|
p = defaultAllocator.resize(p, 10);
|
||||||
|
assert(p.length == 10);
|
||||||
|
|
||||||
|
p = defaultAllocator.resize(p, 0);
|
||||||
|
assert(p is null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroys the object.
|
||||||
|
* Returns the memory should be freed.
|
||||||
|
*/
|
||||||
|
package(tanya) void[] finalize(T)(ref T* p)
|
||||||
|
{
|
||||||
|
if (p is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static if (hasElaborateDestructor!T)
|
||||||
|
{
|
||||||
|
destroy(*p);
|
||||||
|
}
|
||||||
|
return (cast(void*) p)[0 .. T.sizeof];
|
||||||
|
}
|
||||||
|
|
||||||
|
package(tanya) void[] finalize(T)(ref T p)
|
||||||
|
if (isPolymorphicType!T)
|
||||||
|
{
|
||||||
|
if (p is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static if (is(T == interface))
|
||||||
|
{
|
||||||
|
version(Windows)
|
||||||
|
{
|
||||||
|
import core.sys.windows.unknwn : IUnknown;
|
||||||
|
static assert(!is(T : IUnknown), "COM interfaces can't be destroyed in "
|
||||||
|
~ __PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
auto ob = cast(Object) p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias ob = p;
|
||||||
|
}
|
||||||
|
auto ptr = cast(void*) ob;
|
||||||
|
auto support = ptr[0 .. typeid(ob).initializer.length];
|
||||||
|
|
||||||
|
auto ppv = cast(void**) ptr;
|
||||||
|
if (!*ppv)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
auto pc = cast(ClassInfo*) *ppv;
|
||||||
|
scope (exit)
|
||||||
|
{
|
||||||
|
*ppv = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto c = *pc;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Assume the destructor is @nogc. Leave it nothrow since the destructor
|
||||||
|
// shouldn't throw and if it does, it is an error anyway.
|
||||||
|
if (c.destructor)
|
||||||
|
{
|
||||||
|
alias DtorType = void function(Object) pure nothrow @safe @nogc;
|
||||||
|
(cast(DtorType) c.destructor)(ob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((c = c.base) !is null);
|
||||||
|
|
||||||
|
if (ppv[1]) // if monitor is not null
|
||||||
|
{
|
||||||
|
_d_monitordelete(cast(Object) ptr, true);
|
||||||
|
}
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
package(tanya) void[] finalize(T)(ref T[] p)
|
||||||
|
{
|
||||||
|
destroyAll(p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T).
|
||||||
|
* It is assumed the respective entities had been allocated with the same
|
||||||
|
* allocator.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Type of $(D_PARAM p).
|
||||||
|
* allocator = Allocator the $(D_PARAM p) was allocated with.
|
||||||
|
* p = Object or array to be destroyed.
|
||||||
|
*/
|
||||||
|
void dispose(T)(shared Allocator allocator, auto ref T p)
|
||||||
|
{
|
||||||
|
() @trusted { allocator.deallocate(finalize(p)); }();
|
||||||
|
p = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @system unittest
|
||||||
|
{
|
||||||
|
static struct S
|
||||||
|
{
|
||||||
|
~this() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
|
||||||
|
|
||||||
|
defaultAllocator.dispose(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Works with interfaces.
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
interface I
|
||||||
|
{
|
||||||
|
}
|
||||||
|
class C : I
|
||||||
|
{
|
||||||
|
}
|
||||||
|
auto c = defaultAllocator.make!C();
|
||||||
|
I i = c;
|
||||||
|
|
||||||
|
defaultAllocator.dispose(i);
|
||||||
|
defaultAllocator.dispose(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args)
|
||||||
|
* as the parameter list for the constructor of $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Class type.
|
||||||
|
* A = Types of the arguments to the constructor of $(D_PARAM T).
|
||||||
|
* allocator = Allocator.
|
||||||
|
* args = Constructor arguments of $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Returns: Newly created $(D_PSYMBOL T).
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE allocator !is null)
|
||||||
|
*/
|
||||||
|
T make(T, A...)(shared Allocator allocator, auto ref A args)
|
||||||
|
if (is(T == class))
|
||||||
|
in (allocator !is null)
|
||||||
|
{
|
||||||
|
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
||||||
|
if (mem is null)
|
||||||
|
{
|
||||||
|
onOutOfMemoryError();
|
||||||
|
}
|
||||||
|
scope (failure)
|
||||||
|
{
|
||||||
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
|
}
|
||||||
|
|
||||||
|
return emplace!T(mem[0 .. stateSize!T], args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a value object of type $(D_PARAM T) using $(D_PARAM args)
|
||||||
|
* as the parameter list for the constructor of $(D_PARAM T) and returns a
|
||||||
|
* pointer to the new object.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Object type.
|
||||||
|
* A = Types of the arguments to the constructor of $(D_PARAM T).
|
||||||
|
* allocator = Allocator.
|
||||||
|
* args = Constructor arguments of $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Returns: Pointer to the created object.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE allocator !is null)
|
||||||
|
*/
|
||||||
|
T* make(T, A...)(shared Allocator allocator, auto ref A args)
|
||||||
|
if (!is(T == interface)
|
||||||
|
&& !is(T == class)
|
||||||
|
&& !isAssociativeArray!T
|
||||||
|
&& !isArray!T)
|
||||||
|
in (allocator !is null)
|
||||||
|
{
|
||||||
|
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
||||||
|
if (mem is null)
|
||||||
|
{
|
||||||
|
onOutOfMemoryError();
|
||||||
|
}
|
||||||
|
scope (failure)
|
||||||
|
{
|
||||||
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
|
}
|
||||||
|
return emplace!T(mem[0 .. stateSize!T], args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
int* i = defaultAllocator.make!int(5);
|
||||||
|
assert(*i == 5);
|
||||||
|
defaultAllocator.dispose(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new array with $(D_PARAM n) elements.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Array type.
|
||||||
|
* allocator = Allocator.
|
||||||
|
* n = Array size.
|
||||||
|
*
|
||||||
|
* Returns: Newly created array.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE allocator !is null
|
||||||
|
* && n <= size_t.max / ElementType!T.sizeof)
|
||||||
|
*/
|
||||||
|
T make(T)(shared Allocator allocator, const size_t n)
|
||||||
|
if (isArray!T)
|
||||||
|
in (allocator !is null)
|
||||||
|
in (n <= size_t.max / ElementType!T.sizeof)
|
||||||
|
{
|
||||||
|
auto ret = allocator.resize!(ElementType!T)(null, n);
|
||||||
|
ret.uninitializedFill(ElementType!T.init);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
int[] i = defaultAllocator.make!(int[])(2);
|
||||||
|
assert(i.length == 2);
|
||||||
|
assert(i[0] == int.init && i[1] == int.init);
|
||||||
|
defaultAllocator.dispose(i);
|
||||||
|
}
|
@ -3,9 +3,10 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and $(D_PSYMBOL free).
|
* Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and
|
||||||
|
* $(D_PSYMBOL free).
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017-2018.
|
* Copyright: Eugene Wissner 2017-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* Native allocator.
|
* Native allocator.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -17,7 +17,6 @@ module tanya.memory.mmappool;
|
|||||||
version (TanyaNative):
|
version (TanyaNative):
|
||||||
|
|
||||||
import mir.linux._asm.unistd;
|
import mir.linux._asm.unistd;
|
||||||
import tanya.algorithm.comparison;
|
|
||||||
import tanya.memory.allocator;
|
import tanya.memory.allocator;
|
||||||
import tanya.memory.op;
|
import tanya.memory.op;
|
||||||
import tanya.os.error;
|
import tanya.os.error;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Set of operations on memory blocks.
|
* Set of operations on memory blocks.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017-2018.
|
* Copyright: Eugene Wissner 2017-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Dynamic memory management.
|
* Dynamic memory management.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -14,12 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory;
|
module tanya.memory;
|
||||||
|
|
||||||
import tanya.algorithm.mutation;
|
|
||||||
import tanya.conv;
|
import tanya.conv;
|
||||||
import tanya.exception;
|
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
|
public import tanya.memory.lifecycle;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.range.primitive;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mixin generates common methods for classes and structs using
|
* The mixin generates common methods for classes and structs using
|
||||||
@ -86,10 +84,6 @@ mixin template DefaultAllocator()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// From druntime
|
|
||||||
extern (C)
|
|
||||||
private void _d_monitordelete(Object h, bool det) @nogc nothrow pure;
|
|
||||||
|
|
||||||
shared Allocator allocator;
|
shared Allocator allocator;
|
||||||
|
|
||||||
private shared(Allocator) getAllocatorInstance() @nogc nothrow
|
private shared(Allocator) getAllocatorInstance() @nogc nothrow
|
||||||
@ -207,302 +201,3 @@ pure nothrow @safe @nogc
|
|||||||
{
|
{
|
||||||
return (size - 1) / alignment * alignment + alignment;
|
return (size - 1) / alignment * alignment + alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal function used to create, resize or destroy a dynamic array. It
|
|
||||||
* may throw $(D_PSYMBOL OutOfMemoryError). The new
|
|
||||||
* allocated part of the array isn't initialized. This function can be trusted
|
|
||||||
* only in the data structures that can ensure that the array is
|
|
||||||
* allocated/rellocated/deallocated with the same allocator.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* T = Element type of the array being created.
|
|
||||||
* allocator = The allocator used for getting memory.
|
|
||||||
* array = A reference to the array being changed.
|
|
||||||
* length = New array length.
|
|
||||||
*
|
|
||||||
* Returns: $(D_PARAM array).
|
|
||||||
*/
|
|
||||||
package(tanya) T[] resize(T)(shared Allocator allocator,
|
|
||||||
auto ref T[] array,
|
|
||||||
const size_t length) @trusted
|
|
||||||
{
|
|
||||||
if (length == 0)
|
|
||||||
{
|
|
||||||
if (allocator.deallocate(array))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void[] buf = array;
|
|
||||||
if (!allocator.reallocate(buf, length * T.sizeof))
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
// Casting from void[] is unsafe, but we know we cast to the original type.
|
|
||||||
array = cast(T[]) buf;
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
int[] p;
|
|
||||||
|
|
||||||
p = defaultAllocator.resize(p, 20);
|
|
||||||
assert(p.length == 20);
|
|
||||||
|
|
||||||
p = defaultAllocator.resize(p, 30);
|
|
||||||
assert(p.length == 30);
|
|
||||||
|
|
||||||
p = defaultAllocator.resize(p, 10);
|
|
||||||
assert(p.length == 10);
|
|
||||||
|
|
||||||
p = defaultAllocator.resize(p, 0);
|
|
||||||
assert(p is null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destroys the object.
|
|
||||||
* Returns the memory should be freed.
|
|
||||||
*/
|
|
||||||
package(tanya) void[] finalize(T)(ref T* p)
|
|
||||||
{
|
|
||||||
if (p is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
static if (hasElaborateDestructor!T)
|
|
||||||
{
|
|
||||||
destroy(*p);
|
|
||||||
}
|
|
||||||
return (cast(void*) p)[0 .. T.sizeof];
|
|
||||||
}
|
|
||||||
|
|
||||||
package(tanya) void[] finalize(T)(ref T p)
|
|
||||||
if (isPolymorphicType!T)
|
|
||||||
{
|
|
||||||
if (p is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
static if (is(T == interface))
|
|
||||||
{
|
|
||||||
version(Windows)
|
|
||||||
{
|
|
||||||
import core.sys.windows.unknwn : IUnknown;
|
|
||||||
static assert(!is(T : IUnknown), "COM interfaces can't be destroyed in "
|
|
||||||
~ __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
auto ob = cast(Object) p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alias ob = p;
|
|
||||||
}
|
|
||||||
auto ptr = cast(void*) ob;
|
|
||||||
auto support = ptr[0 .. typeid(ob).initializer.length];
|
|
||||||
|
|
||||||
auto ppv = cast(void**) ptr;
|
|
||||||
if (!*ppv)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
auto pc = cast(ClassInfo*) *ppv;
|
|
||||||
scope (exit)
|
|
||||||
{
|
|
||||||
*ppv = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto c = *pc;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// Assume the destructor is @nogc. Leave it nothrow since the destructor
|
|
||||||
// shouldn't throw and if it does, it is an error anyway.
|
|
||||||
if (c.destructor)
|
|
||||||
{
|
|
||||||
alias DtorType = void function(Object) pure nothrow @safe @nogc;
|
|
||||||
(cast(DtorType) c.destructor)(ob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((c = c.base) !is null);
|
|
||||||
|
|
||||||
if (ppv[1]) // if monitor is not null
|
|
||||||
{
|
|
||||||
_d_monitordelete(cast(Object) ptr, true);
|
|
||||||
}
|
|
||||||
return support;
|
|
||||||
}
|
|
||||||
|
|
||||||
package(tanya) void[] finalize(T)(ref T[] p)
|
|
||||||
{
|
|
||||||
destroyAll(p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T).
|
|
||||||
* It is assumed the respective entities had been allocated with the same
|
|
||||||
* allocator.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* T = Type of $(D_PARAM p).
|
|
||||||
* allocator = Allocator the $(D_PARAM p) was allocated with.
|
|
||||||
* p = Object or array to be destroyed.
|
|
||||||
*/
|
|
||||||
void dispose(T)(shared Allocator allocator, auto ref T p)
|
|
||||||
{
|
|
||||||
() @trusted { allocator.deallocate(finalize(p)); }();
|
|
||||||
p = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@nogc nothrow pure @system unittest
|
|
||||||
{
|
|
||||||
static struct S
|
|
||||||
{
|
|
||||||
~this() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
|
|
||||||
|
|
||||||
defaultAllocator.dispose(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Works with interfaces.
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
interface I
|
|
||||||
{
|
|
||||||
}
|
|
||||||
class C : I
|
|
||||||
{
|
|
||||||
}
|
|
||||||
auto c = defaultAllocator.make!C();
|
|
||||||
I i = c;
|
|
||||||
|
|
||||||
defaultAllocator.dispose(i);
|
|
||||||
defaultAllocator.dispose(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args)
|
|
||||||
* as the parameter list for the constructor of $(D_PARAM T).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* T = Class type.
|
|
||||||
* A = Types of the arguments to the constructor of $(D_PARAM T).
|
|
||||||
* allocator = Allocator.
|
|
||||||
* args = Constructor arguments of $(D_PARAM T).
|
|
||||||
*
|
|
||||||
* Returns: Newly created $(D_PSYMBOL T).
|
|
||||||
*
|
|
||||||
* Precondition: $(D_INLINECODE allocator !is null)
|
|
||||||
*/
|
|
||||||
T make(T, A...)(shared Allocator allocator, auto ref A args)
|
|
||||||
if (is(T == class))
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(allocator !is null);
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
|
||||||
if (mem is null)
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
scope (failure)
|
|
||||||
{
|
|
||||||
() @trusted { allocator.deallocate(mem); }();
|
|
||||||
}
|
|
||||||
|
|
||||||
return emplace!T(mem[0 .. stateSize!T], args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a value object of type $(D_PARAM T) using $(D_PARAM args)
|
|
||||||
* as the parameter list for the constructor of $(D_PARAM T) and returns a
|
|
||||||
* pointer to the new object.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* T = Object type.
|
|
||||||
* A = Types of the arguments to the constructor of $(D_PARAM T).
|
|
||||||
* allocator = Allocator.
|
|
||||||
* args = Constructor arguments of $(D_PARAM T).
|
|
||||||
*
|
|
||||||
* Returns: Pointer to the created object.
|
|
||||||
*
|
|
||||||
* Precondition: $(D_INLINECODE allocator !is null)
|
|
||||||
*/
|
|
||||||
T* make(T, A...)(shared Allocator allocator, auto ref A args)
|
|
||||||
if (!is(T == interface)
|
|
||||||
&& !is(T == class)
|
|
||||||
&& !isAssociativeArray!T
|
|
||||||
&& !isArray!T)
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(allocator !is null);
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
|
||||||
if (mem is null)
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
scope (failure)
|
|
||||||
{
|
|
||||||
() @trusted { allocator.deallocate(mem); }();
|
|
||||||
}
|
|
||||||
return emplace!T(mem[0 .. stateSize!T], args);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
int* i = defaultAllocator.make!int(5);
|
|
||||||
assert(*i == 5);
|
|
||||||
defaultAllocator.dispose(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new array with $(D_PARAM n) elements.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* T = Array type.
|
|
||||||
* allocator = Allocator.
|
|
||||||
* n = Array size.
|
|
||||||
*
|
|
||||||
* Returns: Newly created array.
|
|
||||||
*
|
|
||||||
* Precondition: $(D_INLINECODE allocator !is null
|
|
||||||
* && n <= size_t.max / ElementType!T.sizeof)
|
|
||||||
*/
|
|
||||||
T make(T)(shared Allocator allocator, const size_t n)
|
|
||||||
if (isArray!T)
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(allocator !is null);
|
|
||||||
assert(n <= size_t.max / ElementType!T.sizeof);
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
auto ret = allocator.resize!(ElementType!T)(null, n);
|
|
||||||
ret.uninitializedFill(ElementType!T.init);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
int[] i = defaultAllocator.make!(int[])(2);
|
|
||||||
assert(i.length == 2);
|
|
||||||
assert(i[0] == int.init && i[1] == int.init);
|
|
||||||
defaultAllocator.dispose(i);
|
|
||||||
}
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* $(LI Unique ownership)
|
* $(LI Unique ownership)
|
||||||
* )
|
* )
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2018.
|
* Copyright: Eugene Wissner 2016-2019.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -23,10 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory.smartref;
|
module tanya.memory.smartref;
|
||||||
|
|
||||||
import tanya.algorithm.comparison;
|
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.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;
|
||||||
|
Loading…
Reference in New Issue
Block a user