Use dispose from std.experimental
This commit is contained in:
@ -7,12 +7,17 @@
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
*/
|
||||
*/
|
||||
module tanya.memory.allocator;
|
||||
|
||||
import std.experimental.allocator;
|
||||
import std.traits;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
import tanya.memory : defaultAllocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocator interface.
|
||||
*/
|
||||
@ -80,5 +85,23 @@ bool resizeArray(T)(shared Allocator allocator,
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
int[] p;
|
||||
|
||||
defaultAllocator.resizeArray(p, 20);
|
||||
assert(p.length == 20);
|
||||
|
||||
defaultAllocator.resizeArray(p, 30);
|
||||
assert(p.length == 30);
|
||||
|
||||
defaultAllocator.resizeArray(p, 10);
|
||||
assert(p.length == 10);
|
||||
|
||||
defaultAllocator.resizeArray(p, 0);
|
||||
assert(p is null);
|
||||
}
|
||||
|
||||
enum bool isFinalizable(T) = is(T == class) || is(T == interface)
|
||||
|| hasElaborateDestructor!T || isDynamicArray!T;
|
||||
|
@ -7,199 +7,23 @@
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
*/
|
||||
*/
|
||||
module tanya.memory;
|
||||
|
||||
public import tanya.memory.allocator;
|
||||
public import std.experimental.allocator : make, makeArray, expandArray, shrinkArray, IAllocator;
|
||||
import core.atomic;
|
||||
import core.stdc.stdlib;
|
||||
import std.traits;
|
||||
|
||||
version (Windows)
|
||||
public
|
||||
{
|
||||
import core.sys.windows.windows;
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
public import tanya.memory.mmappool;
|
||||
import core.sys.posix.pthread;
|
||||
import tanya.memory.allocator;
|
||||
import std.experimental.allocator : make, dispose, shrinkArray, expandArray, makeArray, dispose;
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
shared Allocator allocator;
|
||||
|
||||
@property ref shared(Allocator) defaultAllocator()
|
||||
{
|
||||
package alias Mutex = CRITICAL_SECTION;
|
||||
package alias destroyMutex = DeleteCriticalSection;
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
package alias Mutex = pthread_mutex_t;
|
||||
package void destroyMutex(pthread_mutex_t* mtx)
|
||||
import tanya.memory.mallocator;
|
||||
if (allocator is null)
|
||||
{
|
||||
pthread_mutex_destroy(mtx) && assert(0);
|
||||
}
|
||||
allocator = Mallocator.instance;
|
||||
}
|
||||
return allocator;
|
||||
}
|
||||
|
||||
@property void defaultAllocator(shared Allocator allocator) @safe nothrow
|
||||
{
|
||||
_defaultAllocator = allocator;
|
||||
}
|
||||
|
||||
@property shared(Allocator) defaultAllocator() @safe nothrow
|
||||
{
|
||||
return _defaultAllocator;
|
||||
}
|
||||
|
||||
static this() @safe nothrow
|
||||
{
|
||||
defaultAllocator = MmapPool.instance;
|
||||
}
|
||||
|
||||
package struct Monitor
|
||||
{
|
||||
Object.Monitor impl; // for user-level monitors
|
||||
void delegate(Object) @nogc[] devt; // for internal monitors
|
||||
size_t refs; // reference count
|
||||
version (Posix)
|
||||
{
|
||||
Mutex mtx;
|
||||
}
|
||||
}
|
||||
|
||||
package @property ref shared(Monitor*) monitor(Object h) pure nothrow
|
||||
{
|
||||
return *cast(shared Monitor**)&h.__monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys and then deallocates (using $(D_PARAM allocator)) the class
|
||||
* object referred to by a $(D_KEYWORD class) or $(D_KEYWORD interface)
|
||||
* reference. It is assumed the respective entities had been allocated with
|
||||
* the same allocator.
|
||||
*
|
||||
* Params:
|
||||
* A = The type of the allocator used for the ojbect allocation.
|
||||
* T = The type of the object that should be destroyed.
|
||||
* allocator = The allocator used for the object allocation.
|
||||
* p = The object should be destroyed.
|
||||
*/
|
||||
void finalize(A, T)(auto ref A allocator, ref T p)
|
||||
if (is(T == class) || is(T == interface))
|
||||
{
|
||||
static if (is(T == interface))
|
||||
{
|
||||
auto ob = cast(Object) p;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias ob = p;
|
||||
}
|
||||
auto pp = cast(void*) ob;
|
||||
auto ppv = cast(void**) pp;
|
||||
if (!pp || !*ppv)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto support = (cast(void*) ob)[0 .. typeid(ob).initializer.length];
|
||||
auto pc = cast(ClassInfo*) *ppv;
|
||||
auto c = *pc;
|
||||
do
|
||||
{
|
||||
if (c.destructor)
|
||||
{
|
||||
(cast(void function(Object)) c.destructor)(ob);
|
||||
}
|
||||
} while ((c = c.base) !is null);
|
||||
|
||||
// Take care of monitors for synchronized blocks
|
||||
if (ppv[1])
|
||||
{
|
||||
shared(Monitor)* m = atomicLoad!(MemoryOrder.acq)(ob.monitor);
|
||||
if (m !is null)
|
||||
{
|
||||
auto mc = cast(Monitor*) m;
|
||||
if (!atomicOp!("-=")(m.refs, cast(size_t) 1))
|
||||
{
|
||||
foreach (v; mc.devt)
|
||||
{
|
||||
if (v)
|
||||
{
|
||||
v(ob);
|
||||
}
|
||||
}
|
||||
if (mc.devt.ptr)
|
||||
{
|
||||
free(mc.devt.ptr);
|
||||
}
|
||||
destroyMutex(&mc.mtx);
|
||||
free(mc);
|
||||
atomicStore!(MemoryOrder.rel)(ob.monitor, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
*ppv = null;
|
||||
|
||||
allocator.deallocate(support);
|
||||
p = null;
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
void finalize(A, T)(auto ref A allocator, ref T *p)
|
||||
if (is(T == struct))
|
||||
{
|
||||
if (p is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static if (hasElaborateDestructor!T)
|
||||
{
|
||||
*p.__xdtor();
|
||||
}
|
||||
allocator.deallocate((cast(void*)p)[0 .. T.sizeof]);
|
||||
p = null;
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
void finalize(A, T)(auto ref A allocator, ref T[] p)
|
||||
{
|
||||
static if (hasElaborateDestructor!T)
|
||||
{
|
||||
foreach (ref e; p)
|
||||
{
|
||||
finalize(allocator, e);
|
||||
}
|
||||
}
|
||||
allocator.deallocate(p);
|
||||
p = null;
|
||||
}
|
||||
|
||||
bool resizeArray(T, A)(auto ref A allocator, ref T[] array, in size_t length)
|
||||
@trusted
|
||||
{
|
||||
if (length == array.length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (array is null && length > 0)
|
||||
{
|
||||
array = makeArray!T(allocator, length);
|
||||
return array !is null;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
finalize(allocator, array);
|
||||
return true;
|
||||
}
|
||||
void[] buf = array;
|
||||
if (!allocator.reallocate(buf, length * T.sizeof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
array = cast(T[]) buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
enum bool isFinalizable(T) = is(T == class) || is(T == interface)
|
||||
|| hasElaborateDestructor!T || isDynamicArray!T;
|
||||
|
||||
private shared Allocator _defaultAllocator;
|
||||
|
Reference in New Issue
Block a user