Use dispose from std.experimental
This commit is contained in:
parent
9241ec503c
commit
721bb110e5
@ -116,7 +116,7 @@ class ReadBuffer : Buffer
|
||||
*/
|
||||
~this()
|
||||
{
|
||||
finalize(allocator, _buffer);
|
||||
dispose(allocator, _buffer);
|
||||
}
|
||||
|
||||
///
|
||||
@ -126,7 +126,7 @@ class ReadBuffer : Buffer
|
||||
assert(b.capacity == 8192);
|
||||
assert(b.length == 0);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +169,7 @@ class ReadBuffer : Buffer
|
||||
b[];
|
||||
assert(b.free == b.blockSize);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,7 +240,7 @@ class ReadBuffer : Buffer
|
||||
assert(result[10] == 20);
|
||||
assert(result[14] == 24);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,7 +275,7 @@ class ReadBuffer : Buffer
|
||||
assert(result[9] == 9);
|
||||
assert(b.length == 0);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +333,7 @@ class WriteBuffer : Buffer
|
||||
*/
|
||||
~this()
|
||||
{
|
||||
finalize(allocator, _buffer);
|
||||
dispose(allocator, _buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,7 +385,7 @@ class WriteBuffer : Buffer
|
||||
b.written = b.length;
|
||||
assert(b.length == 0);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -485,7 +485,7 @@ class WriteBuffer : Buffer
|
||||
assert(b._buffer[0] == 23 && b._buffer[1] == 255
|
||||
&& b._buffer[2] == 48 && b._buffer[3] == 23 && b._buffer[4] == 255);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
|
||||
b = make!WriteBuffer(defaultAllocator, 2);
|
||||
|
||||
@ -495,7 +495,7 @@ class WriteBuffer : Buffer
|
||||
assert(b.ring == 3);
|
||||
assert(b.position == 3);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -578,7 +578,7 @@ class WriteBuffer : Buffer
|
||||
b.written = 4;
|
||||
assert(b.length == 0);
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -631,6 +631,6 @@ class WriteBuffer : Buffer
|
||||
assert(returnedBuf[0..b.length] == buf[0..6]);
|
||||
b.written = b.length;
|
||||
|
||||
finalize(defaultAllocator, b);
|
||||
dispose(defaultAllocator, b);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class SList(T)
|
||||
{
|
||||
static if (isFinalizable!T)
|
||||
{
|
||||
finalize(allocator, front);
|
||||
dispose(allocator, front);
|
||||
}
|
||||
popFront();
|
||||
}
|
||||
@ -87,7 +87,7 @@ class SList(T)
|
||||
l.front = values[1];
|
||||
assert(l.front == values[1]);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +118,7 @@ class SList(T)
|
||||
assert(l.front == value);
|
||||
assert(!l.empty);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +144,7 @@ class SList(T)
|
||||
auto n = first.next.next;
|
||||
auto content = first.next.content;
|
||||
|
||||
finalize(allocator, first.next);
|
||||
dispose(allocator, first.next);
|
||||
first.next = n;
|
||||
|
||||
return content;
|
||||
@ -162,7 +162,7 @@ class SList(T)
|
||||
l.popFront();
|
||||
assert(l.front == values[0]);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +183,7 @@ class SList(T)
|
||||
auto temp = position.next.next;
|
||||
auto content = position.next.content;
|
||||
|
||||
finalize(allocator, position.next);
|
||||
dispose(allocator, position.next);
|
||||
position.next = temp;
|
||||
|
||||
return content;
|
||||
@ -203,7 +203,7 @@ class SList(T)
|
||||
assert(l.remove() == 8);
|
||||
assert(l.empty);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,7 +231,7 @@ class SList(T)
|
||||
l.reset();
|
||||
assert(l.current == 5);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,7 +275,7 @@ class SList(T)
|
||||
assert(i != 2 || e == values[0]);
|
||||
}
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
@ -315,7 +315,7 @@ class SList(T)
|
||||
++i;
|
||||
}
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -400,5 +400,5 @@ unittest
|
||||
{
|
||||
auto l = make!(SList!Stuff)(defaultAllocator);
|
||||
|
||||
finalize(defaultAllocator, l);
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class Queue(T)
|
||||
{
|
||||
static if (isFinalizable!T)
|
||||
{
|
||||
finalize(allocator, e);
|
||||
dispose(allocator, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ class Queue(T)
|
||||
q.insertBack(values[1]);
|
||||
assert(q.front is values[0]);
|
||||
|
||||
finalize(defaultAllocator, q);
|
||||
dispose(defaultAllocator, q);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +129,7 @@ class Queue(T)
|
||||
assert(q.front == value);
|
||||
assert(!q.empty);
|
||||
|
||||
finalize(defaultAllocator, q);
|
||||
dispose(defaultAllocator, q);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +150,7 @@ class Queue(T)
|
||||
q.insertBack(value);
|
||||
assert(!q.empty);
|
||||
|
||||
finalize(defaultAllocator, q);
|
||||
dispose(defaultAllocator, q);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +167,7 @@ class Queue(T)
|
||||
{
|
||||
auto n = first.next.next;
|
||||
|
||||
finalize(allocator, first.next);
|
||||
dispose(allocator, first.next);
|
||||
first.next = n;
|
||||
|
||||
return this;
|
||||
@ -185,7 +185,7 @@ class Queue(T)
|
||||
q.popFront();
|
||||
assert(q.front is values[1]);
|
||||
|
||||
finalize(defaultAllocator, q);
|
||||
dispose(defaultAllocator, q);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,5 +214,5 @@ unittest
|
||||
{
|
||||
auto q = make!(Queue!int)(defaultAllocator);
|
||||
|
||||
finalize(defaultAllocator, q);
|
||||
dispose(defaultAllocator, q);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import tanya.memory;
|
||||
*
|
||||
* v[1000] = value;
|
||||
*
|
||||
* finalize(defaultAllocator, v);
|
||||
* dispose(defaultAllocator, v);
|
||||
* ---
|
||||
* it will allocate not only for one, but for 1000 elements. So this
|
||||
* implementation is more suitable for sequential data with random access.
|
||||
@ -57,7 +57,7 @@ class Vector(T)
|
||||
*/
|
||||
~this()
|
||||
{
|
||||
finalize(allocator, vector);
|
||||
dispose(allocator, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +94,7 @@ class Vector(T)
|
||||
v.length = 0;
|
||||
assert(v.length == 0);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,7 +116,7 @@ class Vector(T)
|
||||
void remove(size_t pos)
|
||||
{
|
||||
auto el = vector[pos];
|
||||
finalize(allocator, el);
|
||||
dispose(allocator, el);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ class Vector(T)
|
||||
v[4] = values[1];
|
||||
assert(v.length == 5);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,7 +182,7 @@ class Vector(T)
|
||||
v[0] = values[1];
|
||||
assert(v[0] is values[1]);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,7 +250,7 @@ class Vector(T)
|
||||
assert(j != 2 || e is values[2]);
|
||||
}
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,7 +289,7 @@ class Vector(T)
|
||||
v.front = values[1];
|
||||
assert(v.front == 15);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,7 +325,7 @@ class Vector(T)
|
||||
v.popFront();
|
||||
assert(v.empty);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,7 +364,7 @@ class Vector(T)
|
||||
v.back = values[1];
|
||||
assert(v.back == 15);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,7 +399,7 @@ class Vector(T)
|
||||
v.popBack();
|
||||
assert(v.empty);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
||||
/// Container.
|
||||
@ -413,5 +413,5 @@ unittest
|
||||
{
|
||||
auto v = make!(Vector!int)(defaultAllocator);
|
||||
|
||||
finalize(defaultAllocator, v);
|
||||
dispose(defaultAllocator, v);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ unittest
|
||||
assert(input.length == 64);
|
||||
assert(input[63] == 0);
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.dispose(input);
|
||||
}
|
||||
{ // PKCS#7
|
||||
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||
@ -139,7 +139,7 @@ unittest
|
||||
}
|
||||
}
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.dispose(input);
|
||||
}
|
||||
{ // ANSI X.923
|
||||
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||
@ -184,7 +184,7 @@ unittest
|
||||
}
|
||||
}
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.dispose(input);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,8 +240,8 @@ unittest
|
||||
removePadding(input, Mode.zero, 64);
|
||||
assert(input == inputDup);
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.finalize(inputDup);
|
||||
defaultAllocator.dispose(input);
|
||||
defaultAllocator.dispose(inputDup);
|
||||
|
||||
}
|
||||
{ // PKCS#7
|
||||
@ -257,8 +257,8 @@ unittest
|
||||
removePadding(input, Mode.pkcs7, 64);
|
||||
assert(input == inputDup);
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.finalize(inputDup);
|
||||
defaultAllocator.dispose(input);
|
||||
defaultAllocator.dispose(inputDup);
|
||||
}
|
||||
{ // ANSI X.923
|
||||
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||
@ -273,7 +273,7 @@ unittest
|
||||
removePadding(input, Mode.pkcs7, 64);
|
||||
assert(input == inputDup);
|
||||
|
||||
defaultAllocator.finalize(input);
|
||||
defaultAllocator.finalize(inputDup);
|
||||
defaultAllocator.dispose(input);
|
||||
defaultAllocator.dispose(inputDup);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class EpollLoop : Loop
|
||||
*/
|
||||
~this()
|
||||
{
|
||||
finalize(defaultAllocator, epollEvents);
|
||||
dispose(defaultAllocator, epollEvents);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +125,7 @@ class EpollLoop : Loop
|
||||
// If it is a ConnectionWatcher
|
||||
if (connection is null && connections[client] !is null)
|
||||
{
|
||||
finalize(defaultAllocator, connections[client]);
|
||||
dispose(defaultAllocator, connections[client]);
|
||||
connections[client] = null;
|
||||
}
|
||||
}
|
||||
@ -198,7 +198,7 @@ class EpollLoop : Loop
|
||||
catch (TransportException e)
|
||||
{
|
||||
swapPendings.insertBack(connection);
|
||||
finalize(defaultAllocator, e);
|
||||
dispose(defaultAllocator, e);
|
||||
}
|
||||
}
|
||||
else if (ev.events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
|
||||
|
@ -61,9 +61,9 @@ class SocketTransport : DuplexTransport
|
||||
~this()
|
||||
{
|
||||
close(socket);
|
||||
finalize(defaultAllocator, input_);
|
||||
finalize(defaultAllocator, output_);
|
||||
finalize(defaultAllocator, protocol_);
|
||||
dispose(defaultAllocator, input_);
|
||||
dispose(defaultAllocator, output_);
|
||||
dispose(defaultAllocator, protocol_);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,9 +70,9 @@ abstract class Loop
|
||||
*/
|
||||
~this()
|
||||
{
|
||||
finalize(defaultAllocator, connections);
|
||||
finalize(defaultAllocator, pendings);
|
||||
finalize(defaultAllocator, swapPendings);
|
||||
dispose(defaultAllocator, connections);
|
||||
dispose(defaultAllocator, pendings);
|
||||
dispose(defaultAllocator, swapPendings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +128,7 @@ class IOWatcher : ConnectionWatcher
|
||||
|
||||
~this()
|
||||
{
|
||||
finalize(defaultAllocator, transport_);
|
||||
dispose(defaultAllocator, transport_);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +185,7 @@ class IOWatcher : ConnectionWatcher
|
||||
else if (transport.disconnected)
|
||||
{
|
||||
transport.protocol.disconnected();
|
||||
finalize(defaultAllocator, transport_);
|
||||
dispose(defaultAllocator, transport_);
|
||||
protocolFactory = null;
|
||||
}
|
||||
else if (transport.output.length)
|
||||
@ -200,7 +200,7 @@ class IOWatcher : ConnectionWatcher
|
||||
}
|
||||
catch (TransportException e)
|
||||
{
|
||||
finalize(defaultAllocator, e);
|
||||
dispose(defaultAllocator, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user