Use dispose from std.experimental

This commit is contained in:
Eugen Wissner 2016-10-05 13:12:50 +02:00
parent 9241ec503c
commit 721bb110e5
11 changed files with 98 additions and 251 deletions

View File

@ -116,7 +116,7 @@ class ReadBuffer : Buffer
*/ */
~this() ~this()
{ {
finalize(allocator, _buffer); dispose(allocator, _buffer);
} }
/// ///
@ -126,7 +126,7 @@ class ReadBuffer : Buffer
assert(b.capacity == 8192); assert(b.capacity == 8192);
assert(b.length == 0); assert(b.length == 0);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
/** /**
@ -169,7 +169,7 @@ class ReadBuffer : Buffer
b[]; b[];
assert(b.free == b.blockSize); assert(b.free == b.blockSize);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
/** /**
@ -240,7 +240,7 @@ class ReadBuffer : Buffer
assert(result[10] == 20); assert(result[10] == 20);
assert(result[14] == 24); assert(result[14] == 24);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
/** /**
@ -275,7 +275,7 @@ class ReadBuffer : Buffer
assert(result[9] == 9); assert(result[9] == 9);
assert(b.length == 0); assert(b.length == 0);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
} }
@ -333,7 +333,7 @@ class WriteBuffer : Buffer
*/ */
~this() ~this()
{ {
finalize(allocator, _buffer); dispose(allocator, _buffer);
} }
/** /**
@ -385,7 +385,7 @@ class WriteBuffer : Buffer
b.written = b.length; b.written = b.length;
assert(b.length == 0); 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 assert(b._buffer[0] == 23 && b._buffer[1] == 255
&& b._buffer[2] == 48 && b._buffer[3] == 23 && b._buffer[4] == 255); && b._buffer[2] == 48 && b._buffer[3] == 23 && b._buffer[4] == 255);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
b = make!WriteBuffer(defaultAllocator, 2); b = make!WriteBuffer(defaultAllocator, 2);
@ -495,7 +495,7 @@ class WriteBuffer : Buffer
assert(b.ring == 3); assert(b.ring == 3);
assert(b.position == 3); assert(b.position == 3);
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
/** /**
@ -578,7 +578,7 @@ class WriteBuffer : Buffer
b.written = 4; b.written = 4;
assert(b.length == 0); 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]); assert(returnedBuf[0..b.length] == buf[0..6]);
b.written = b.length; b.written = b.length;
finalize(defaultAllocator, b); dispose(defaultAllocator, b);
} }
} }

View File

@ -42,7 +42,7 @@ class SList(T)
{ {
static if (isFinalizable!T) static if (isFinalizable!T)
{ {
finalize(allocator, front); dispose(allocator, front);
} }
popFront(); popFront();
} }
@ -87,7 +87,7 @@ class SList(T)
l.front = values[1]; l.front = values[1];
assert(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.front == value);
assert(!l.empty); assert(!l.empty);
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/** /**
@ -144,7 +144,7 @@ class SList(T)
auto n = first.next.next; auto n = first.next.next;
auto content = first.next.content; auto content = first.next.content;
finalize(allocator, first.next); dispose(allocator, first.next);
first.next = n; first.next = n;
return content; return content;
@ -162,7 +162,7 @@ class SList(T)
l.popFront(); l.popFront();
assert(l.front == values[0]); assert(l.front == values[0]);
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/** /**
@ -183,7 +183,7 @@ class SList(T)
auto temp = position.next.next; auto temp = position.next.next;
auto content = position.next.content; auto content = position.next.content;
finalize(allocator, position.next); dispose(allocator, position.next);
position.next = temp; position.next = temp;
return content; return content;
@ -203,7 +203,7 @@ class SList(T)
assert(l.remove() == 8); assert(l.remove() == 8);
assert(l.empty); assert(l.empty);
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/** /**
@ -231,7 +231,7 @@ class SList(T)
l.reset(); l.reset();
assert(l.current == 5); assert(l.current == 5);
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/** /**
@ -275,7 +275,7 @@ class SList(T)
assert(i != 2 || e == values[0]); assert(i != 2 || e == values[0]);
} }
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/// Ditto. /// Ditto.
@ -315,7 +315,7 @@ class SList(T)
++i; ++i;
} }
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }
/** /**
@ -400,5 +400,5 @@ unittest
{ {
auto l = make!(SList!Stuff)(defaultAllocator); auto l = make!(SList!Stuff)(defaultAllocator);
finalize(defaultAllocator, l); dispose(defaultAllocator, l);
} }

View File

@ -41,7 +41,7 @@ class Queue(T)
{ {
static if (isFinalizable!T) static if (isFinalizable!T)
{ {
finalize(allocator, e); dispose(allocator, e);
} }
} }
} }
@ -99,7 +99,7 @@ class Queue(T)
q.insertBack(values[1]); q.insertBack(values[1]);
assert(q.front is values[0]); 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.front == value);
assert(!q.empty); assert(!q.empty);
finalize(defaultAllocator, q); dispose(defaultAllocator, q);
} }
/** /**
@ -150,7 +150,7 @@ class Queue(T)
q.insertBack(value); q.insertBack(value);
assert(!q.empty); assert(!q.empty);
finalize(defaultAllocator, q); dispose(defaultAllocator, q);
} }
/** /**
@ -167,7 +167,7 @@ class Queue(T)
{ {
auto n = first.next.next; auto n = first.next.next;
finalize(allocator, first.next); dispose(allocator, first.next);
first.next = n; first.next = n;
return this; return this;
@ -185,7 +185,7 @@ class Queue(T)
q.popFront(); q.popFront();
assert(q.front is values[1]); assert(q.front is values[1]);
finalize(defaultAllocator, q); dispose(defaultAllocator, q);
} }
/** /**
@ -214,5 +214,5 @@ unittest
{ {
auto q = make!(Queue!int)(defaultAllocator); auto q = make!(Queue!int)(defaultAllocator);
finalize(defaultAllocator, q); dispose(defaultAllocator, q);
} }

View File

@ -22,7 +22,7 @@ import tanya.memory;
* *
* v[1000] = value; * v[1000] = value;
* *
* finalize(defaultAllocator, v); * dispose(defaultAllocator, v);
* --- * ---
* it will allocate not only for one, but for 1000 elements. So this * it will allocate not only for one, but for 1000 elements. So this
* implementation is more suitable for sequential data with random access. * implementation is more suitable for sequential data with random access.
@ -57,7 +57,7 @@ class Vector(T)
*/ */
~this() ~this()
{ {
finalize(allocator, vector); dispose(allocator, vector);
} }
/** /**
@ -94,7 +94,7 @@ class Vector(T)
v.length = 0; v.length = 0;
assert(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) void remove(size_t pos)
{ {
auto el = vector[pos]; auto el = vector[pos];
finalize(allocator, el); dispose(allocator, el);
} }
} }
@ -151,7 +151,7 @@ class Vector(T)
v[4] = values[1]; v[4] = values[1];
assert(v.length == 5); assert(v.length == 5);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/** /**
@ -182,7 +182,7 @@ class Vector(T)
v[0] = values[1]; v[0] = values[1];
assert(v[0] is 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]); assert(j != 2 || e is values[2]);
} }
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/** /**
@ -289,7 +289,7 @@ class Vector(T)
v.front = values[1]; v.front = values[1];
assert(v.front == 15); assert(v.front == 15);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/** /**
@ -325,7 +325,7 @@ class Vector(T)
v.popFront(); v.popFront();
assert(v.empty); assert(v.empty);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/** /**
@ -364,7 +364,7 @@ class Vector(T)
v.back = values[1]; v.back = values[1];
assert(v.back == 15); assert(v.back == 15);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/** /**
@ -399,7 +399,7 @@ class Vector(T)
v.popBack(); v.popBack();
assert(v.empty); assert(v.empty);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }
/// Container. /// Container.
@ -413,5 +413,5 @@ unittest
{ {
auto v = make!(Vector!int)(defaultAllocator); auto v = make!(Vector!int)(defaultAllocator);
finalize(defaultAllocator, v); dispose(defaultAllocator, v);
} }

View File

@ -94,7 +94,7 @@ unittest
assert(input.length == 64); assert(input.length == 64);
assert(input[63] == 0); assert(input[63] == 0);
defaultAllocator.finalize(input); defaultAllocator.dispose(input);
} }
{ // PKCS#7 { // PKCS#7
auto input = defaultAllocator.makeArray!ubyte(50); auto input = defaultAllocator.makeArray!ubyte(50);
@ -139,7 +139,7 @@ unittest
} }
} }
defaultAllocator.finalize(input); defaultAllocator.dispose(input);
} }
{ // ANSI X.923 { // ANSI X.923
auto input = defaultAllocator.makeArray!ubyte(50); 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); removePadding(input, Mode.zero, 64);
assert(input == inputDup); assert(input == inputDup);
defaultAllocator.finalize(input); defaultAllocator.dispose(input);
defaultAllocator.finalize(inputDup); defaultAllocator.dispose(inputDup);
} }
{ // PKCS#7 { // PKCS#7
@ -257,8 +257,8 @@ unittest
removePadding(input, Mode.pkcs7, 64); removePadding(input, Mode.pkcs7, 64);
assert(input == inputDup); assert(input == inputDup);
defaultAllocator.finalize(input); defaultAllocator.dispose(input);
defaultAllocator.finalize(inputDup); defaultAllocator.dispose(inputDup);
} }
{ // ANSI X.923 { // ANSI X.923
auto input = defaultAllocator.makeArray!ubyte(50); auto input = defaultAllocator.makeArray!ubyte(50);
@ -273,7 +273,7 @@ unittest
removePadding(input, Mode.pkcs7, 64); removePadding(input, Mode.pkcs7, 64);
assert(input == inputDup); assert(input == inputDup);
defaultAllocator.finalize(input); defaultAllocator.dispose(input);
defaultAllocator.finalize(inputDup); defaultAllocator.dispose(inputDup);
} }
} }

View File

@ -59,7 +59,7 @@ class EpollLoop : Loop
*/ */
~this() ~this()
{ {
finalize(defaultAllocator, epollEvents); dispose(defaultAllocator, epollEvents);
} }
/** /**
@ -125,7 +125,7 @@ class EpollLoop : Loop
// If it is a ConnectionWatcher // If it is a ConnectionWatcher
if (connection is null && connections[client] !is null) if (connection is null && connections[client] !is null)
{ {
finalize(defaultAllocator, connections[client]); dispose(defaultAllocator, connections[client]);
connections[client] = null; connections[client] = null;
} }
} }
@ -198,7 +198,7 @@ class EpollLoop : Loop
catch (TransportException e) catch (TransportException e)
{ {
swapPendings.insertBack(connection); swapPendings.insertBack(connection);
finalize(defaultAllocator, e); dispose(defaultAllocator, e);
} }
} }
else if (ev.events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) else if (ev.events & (EPOLLOUT | EPOLLERR | EPOLLHUP))

View File

@ -61,9 +61,9 @@ class SocketTransport : DuplexTransport
~this() ~this()
{ {
close(socket); close(socket);
finalize(defaultAllocator, input_); dispose(defaultAllocator, input_);
finalize(defaultAllocator, output_); dispose(defaultAllocator, output_);
finalize(defaultAllocator, protocol_); dispose(defaultAllocator, protocol_);
} }
/** /**

View File

@ -70,9 +70,9 @@ abstract class Loop
*/ */
~this() ~this()
{ {
finalize(defaultAllocator, connections); dispose(defaultAllocator, connections);
finalize(defaultAllocator, pendings); dispose(defaultAllocator, pendings);
finalize(defaultAllocator, swapPendings); dispose(defaultAllocator, swapPendings);
} }
/** /**

View File

@ -128,7 +128,7 @@ class IOWatcher : ConnectionWatcher
~this() ~this()
{ {
finalize(defaultAllocator, transport_); dispose(defaultAllocator, transport_);
} }
/** /**
@ -185,7 +185,7 @@ class IOWatcher : ConnectionWatcher
else if (transport.disconnected) else if (transport.disconnected)
{ {
transport.protocol.disconnected(); transport.protocol.disconnected();
finalize(defaultAllocator, transport_); dispose(defaultAllocator, transport_);
protocolFactory = null; protocolFactory = null;
} }
else if (transport.output.length) else if (transport.output.length)
@ -200,7 +200,7 @@ class IOWatcher : ConnectionWatcher
} }
catch (TransportException e) catch (TransportException e)
{ {
finalize(defaultAllocator, e); dispose(defaultAllocator, e);
} }
} }
} }

View File

@ -7,12 +7,17 @@
* 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)
*/ */
module tanya.memory.allocator; module tanya.memory.allocator;
import std.experimental.allocator; import std.experimental.allocator;
import std.traits; import std.traits;
version (unittest)
{
import tanya.memory : defaultAllocator;
}
/** /**
* Allocator interface. * Allocator interface.
*/ */
@ -80,5 +85,23 @@ bool resizeArray(T)(shared Allocator allocator,
return true; 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) enum bool isFinalizable(T) = is(T == class) || is(T == interface)
|| hasElaborateDestructor!T || isDynamicArray!T; || hasElaborateDestructor!T || isDynamicArray!T;

View File

@ -7,199 +7,23 @@
* 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)
*/ */
module tanya.memory; module tanya.memory;
public import tanya.memory.allocator; public
public import std.experimental.allocator : make, makeArray, expandArray, shrinkArray, IAllocator;
import core.atomic;
import core.stdc.stdlib;
import std.traits;
version (Windows)
{ {
import core.sys.windows.windows; import tanya.memory.allocator;
} import std.experimental.allocator : make, dispose, shrinkArray, expandArray, makeArray, dispose;
else version (Posix)
{
public import tanya.memory.mmappool;
import core.sys.posix.pthread;
} }
version (Windows) shared Allocator allocator;
@property ref shared(Allocator) defaultAllocator()
{ {
package alias Mutex = CRITICAL_SECTION; import tanya.memory.mallocator;
package alias destroyMutex = DeleteCriticalSection; if (allocator is null)
}
else version (Posix)
{
package alias Mutex = pthread_mutex_t;
package void destroyMutex(pthread_mutex_t* mtx)
{ {
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;