Make allocator shared and fix some RefCounted bugs
This commit is contained in:
parent
b3fdd6fd4a
commit
fa607141e4
@ -107,7 +107,7 @@ class EpollLoop : SelectorLoop
|
|||||||
{
|
{
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!BadLoopException();
|
throw defaultAllocator.make!BadLoopException();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class IOCPStreamTransport : StreamTransport
|
|||||||
body
|
body
|
||||||
{
|
{
|
||||||
socket_ = socket;
|
socket_ = socket;
|
||||||
input = MmapPool.instance.make!WriteBuffer();
|
input = MmapPool.instance.make!WriteBuffer(8192, MmapPool.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this()
|
||||||
@ -101,7 +101,8 @@ class IOCPStreamTransport : StreamTransport
|
|||||||
completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
||||||
if (!completionPort)
|
if (!completionPort)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!BadLoopException("Creating completion port failed");
|
throw make!BadLoopException(defaultAllocator,
|
||||||
|
"Creating completion port failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ class IOCPStreamTransport : StreamTransport
|
|||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
MmapPool.instance.dispose(overlapped);
|
||||||
theAllocator.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +174,7 @@ class IOCPStreamTransport : StreamTransport
|
|||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
MmapPool.instance.dispose(overlapped);
|
||||||
theAllocator.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ class KqueueLoop : SelectorLoop
|
|||||||
{
|
{
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!BadLoopException();
|
throw defaultAllocatorAllocator.make!BadLoopException();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class SelectorStreamTransport : StreamTransport
|
|||||||
{
|
{
|
||||||
socket_ = socket;
|
socket_ = socket;
|
||||||
this.loop = loop;
|
this.loop = loop;
|
||||||
input = MmapPool.instance.make!WriteBuffer();
|
input = MmapPool.instance.make!WriteBuffer(8192, MmapPool.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,7 +224,7 @@ abstract class SelectorLoop : Loop
|
|||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
theAllocator.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (client is null)
|
if (client is null)
|
||||||
|
@ -34,31 +34,31 @@
|
|||||||
*
|
*
|
||||||
* void main()
|
* void main()
|
||||||
* {
|
* {
|
||||||
* auto address = theAllocator.make!InternetAddress("127.0.0.1", cast(ushort) 8192);
|
* auto address = defaultAllocator.make!InternetAddress("127.0.0.1", cast(ushort) 8192);
|
||||||
*
|
*
|
||||||
* version (Windows)
|
* version (Windows)
|
||||||
* {
|
* {
|
||||||
* auto sock = theAllocator.make!OverlappedStreamSocket(AddressFamily.INET);
|
* auto sock = defaultAllocator.make!OverlappedStreamSocket(AddressFamily.INET);
|
||||||
* }
|
* }
|
||||||
* else
|
* else
|
||||||
* {
|
* {
|
||||||
* auto sock = theAllocator.make!StreamSocket(AddressFamily.INET);
|
* auto sock = defaultAllocator.make!StreamSocket(AddressFamily.INET);
|
||||||
* sock.blocking = false;
|
* sock.blocking = false;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* sock.bind(address);
|
* sock.bind(address);
|
||||||
* sock.listen(5);
|
* sock.listen(5);
|
||||||
*
|
*
|
||||||
* auto io = theAllocator.make!ConnectionWatcher(sock);
|
* auto io = defaultAllocator.make!ConnectionWatcher(sock);
|
||||||
* io.setProtocol!EchoProtocol;
|
* io.setProtocol!EchoProtocol;
|
||||||
*
|
*
|
||||||
* defaultLoop.start(io);
|
* defaultLoop.start(io);
|
||||||
* defaultLoop.run();
|
* defaultLoop.run();
|
||||||
*
|
*
|
||||||
* sock.shutdown();
|
* sock.shutdown();
|
||||||
* theAllocator.dispose(io);
|
* defaultAllocator.dispose(io);
|
||||||
* theAllocator.dispose(sock);
|
* defaultAllocator.dispose(sock);
|
||||||
* theAllocator.dispose(address);
|
* defaultAllocator.dispose(address);
|
||||||
* }
|
* }
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
@ -278,7 +278,7 @@ abstract class Loop
|
|||||||
protected void kill(IOWatcher watcher, SocketException exception)
|
protected void kill(IOWatcher watcher, SocketException exception)
|
||||||
{
|
{
|
||||||
watcher.socket.shutdown();
|
watcher.socket.shutdown();
|
||||||
theAllocator.dispose(watcher.socket);
|
defaultAllocator.dispose(watcher.socket);
|
||||||
MmapPool.instance.dispose(watcher.transport);
|
MmapPool.instance.dispose(watcher.transport);
|
||||||
watcher.exception = exception;
|
watcher.exception = exception;
|
||||||
swapPendings.insertBack(watcher);
|
swapPendings.insertBack(watcher);
|
||||||
|
@ -157,7 +157,7 @@ class IOWatcher : ConnectionWatcher
|
|||||||
super();
|
super();
|
||||||
transport_ = transport;
|
transport_ = transport;
|
||||||
protocol_ = protocol;
|
protocol_ = protocol;
|
||||||
output = MmapPool.instance.make!ReadBuffer();
|
output = MmapPool.instance.make!ReadBuffer(8192, 1024, MmapPool.instance);
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,11 +108,15 @@ class ReadBuffer : Buffer
|
|||||||
/// Size by which the buffer will grow.
|
/// Size by which the buffer will grow.
|
||||||
protected immutable size_t blockSize;
|
protected immutable size_t blockSize;
|
||||||
|
|
||||||
|
/// Allocator.
|
||||||
|
protected shared Allocator allocator;
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
assert(length_ <= buffer_.length);
|
assert(length_ <= buffer_.length);
|
||||||
assert(blockSize > 0);
|
assert(blockSize > 0);
|
||||||
assert(minAvailable > 0);
|
assert(minAvailable > 0);
|
||||||
|
assert(allocator !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,15 +127,17 @@ class ReadBuffer : Buffer
|
|||||||
* will grow.
|
* will grow.
|
||||||
* minAvailable = minimal size should be always available to fill.
|
* minAvailable = minimal size should be always available to fill.
|
||||||
* So it will reallocate if $(D_INLINECODE
|
* So it will reallocate if $(D_INLINECODE
|
||||||
* $(D_PSYMBOL free) < $(D_PARAM minAvailable)
|
* $(D_PSYMBOL free) < $(D_PARAM minAvailable)).
|
||||||
* ).
|
* allocator = Allocator.
|
||||||
*/
|
*/
|
||||||
this(size_t size = 8192,
|
this(size_t size = 8192,
|
||||||
size_t minAvailable = 1024)
|
size_t minAvailable = 1024,
|
||||||
|
shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
this.minAvailable = minAvailable;
|
this.minAvailable = minAvailable;
|
||||||
this.blockSize = size;
|
this.blockSize = size;
|
||||||
theAllocator.resizeArray!ubyte(buffer_, size);
|
this.allocator = allocator;
|
||||||
|
allocator.resizeArray!ubyte(buffer_, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,17 +145,17 @@ class ReadBuffer : Buffer
|
|||||||
*/
|
*/
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
theAllocator.dispose(buffer_);
|
allocator.dispose(buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!ReadBuffer;
|
auto b = defaultAllocator.make!ReadBuffer;
|
||||||
assert(b.capacity == 8192);
|
assert(b.capacity == 8192);
|
||||||
assert(b.length == 0);
|
assert(b.length == 0);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -190,7 +196,7 @@ class ReadBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!ReadBuffer;
|
auto b = defaultAllocator.make!ReadBuffer;
|
||||||
size_t numberRead;
|
size_t numberRead;
|
||||||
|
|
||||||
// Fills the buffer with values 0..10
|
// Fills the buffer with values 0..10
|
||||||
@ -202,7 +208,7 @@ class ReadBuffer : Buffer
|
|||||||
b.clear();
|
b.clear();
|
||||||
assert(b.free == b.blockSize);
|
assert(b.free == b.blockSize);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,7 +230,7 @@ class ReadBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!ReadBuffer;
|
auto b = defaultAllocator.make!ReadBuffer;
|
||||||
size_t numberRead;
|
size_t numberRead;
|
||||||
ubyte[] result;
|
ubyte[] result;
|
||||||
|
|
||||||
@ -252,7 +258,7 @@ class ReadBuffer : Buffer
|
|||||||
assert(result[10] == 20);
|
assert(result[10] == 20);
|
||||||
assert(result[14] == 24);
|
assert(result[14] == 24);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -294,7 +300,7 @@ class ReadBuffer : Buffer
|
|||||||
{
|
{
|
||||||
if (capacity - length < minAvailable)
|
if (capacity - length < minAvailable)
|
||||||
{
|
{
|
||||||
theAllocator.resizeArray!ubyte(buffer_, capacity + blockSize);
|
allocator.resizeArray!ubyte(buffer_, capacity + blockSize);
|
||||||
}
|
}
|
||||||
ring = length_;
|
ring = length_;
|
||||||
return buffer_[length_..$];
|
return buffer_[length_..$];
|
||||||
@ -304,7 +310,7 @@ class ReadBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!ReadBuffer;
|
auto b = defaultAllocator.make!ReadBuffer;
|
||||||
size_t numberRead;
|
size_t numberRead;
|
||||||
ubyte[] result;
|
ubyte[] result;
|
||||||
|
|
||||||
@ -319,7 +325,7 @@ class ReadBuffer : Buffer
|
|||||||
b.clear();
|
b.clear();
|
||||||
assert(b.length == 0);
|
assert(b.length == 0);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,23 +355,29 @@ class WriteBuffer : Buffer
|
|||||||
/// The position of the free area in the buffer.
|
/// The position of the free area in the buffer.
|
||||||
protected size_t position;
|
protected size_t position;
|
||||||
|
|
||||||
|
/// Allocator.
|
||||||
|
protected shared Allocator allocator;
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
assert(blockSize > 0);
|
assert(blockSize > 0);
|
||||||
// position can refer to an element outside the buffer if the buffer is full.
|
// position can refer to an element outside the buffer if the buffer is full.
|
||||||
assert(position <= buffer_.length);
|
assert(position <= buffer_.length);
|
||||||
|
assert(allocator !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Params:
|
* Params:
|
||||||
* size = Initial buffer size and the size by which the buffer
|
* size = Initial buffer size and the size by which the buffer will
|
||||||
* will grow.
|
* grow.
|
||||||
|
* allocator = Allocator.
|
||||||
*/
|
*/
|
||||||
this(size_t size = 8192)
|
this(size_t size = 8192, shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
|
this.allocator = allocator;
|
||||||
blockSize = size;
|
blockSize = size;
|
||||||
ring = size - 1;
|
ring = size - 1;
|
||||||
theAllocator.resizeArray!ubyte(buffer_, size);
|
allocator.resizeArray!ubyte(buffer_, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -373,7 +385,7 @@ class WriteBuffer : Buffer
|
|||||||
*/
|
*/
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
theAllocator.dispose(buffer_);
|
allocator.dispose(buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -415,7 +427,7 @@ class WriteBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!WriteBuffer(4);
|
auto b = defaultAllocator.make!WriteBuffer(4);
|
||||||
ubyte[3] buf = [48, 23, 255];
|
ubyte[3] buf = [48, 23, 255];
|
||||||
|
|
||||||
b ~= buf;
|
b ~= buf;
|
||||||
@ -433,7 +445,7 @@ class WriteBuffer : Buffer
|
|||||||
b += b.length;
|
b += b.length;
|
||||||
assert(b.length == 0);
|
assert(b.length == 0);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -498,7 +510,7 @@ class WriteBuffer : Buffer
|
|||||||
{
|
{
|
||||||
auto newSize = end / blockSize * blockSize + blockSize;
|
auto newSize = end / blockSize * blockSize + blockSize;
|
||||||
|
|
||||||
theAllocator.resizeArray!ubyte(buffer_, newSize);
|
allocator.resizeArray!ubyte(buffer_, newSize);
|
||||||
}
|
}
|
||||||
buffer_[position..end] = buffer[start..$];
|
buffer_[position..end] = buffer[start..$];
|
||||||
position = end;
|
position = end;
|
||||||
@ -514,7 +526,7 @@ class WriteBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!WriteBuffer(4);
|
auto b = defaultAllocator.make!WriteBuffer(4);
|
||||||
ubyte[3] buf = [48, 23, 255];
|
ubyte[3] buf = [48, 23, 255];
|
||||||
|
|
||||||
b ~= buf;
|
b ~= buf;
|
||||||
@ -533,9 +545,9 @@ 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);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
|
|
||||||
b = make!WriteBuffer(theAllocator, 2);
|
b = make!WriteBuffer(defaultAllocator, 2);
|
||||||
|
|
||||||
b ~= buf;
|
b ~= buf;
|
||||||
assert(b.start == 0);
|
assert(b.start == 0);
|
||||||
@ -543,7 +555,7 @@ class WriteBuffer : Buffer
|
|||||||
assert(b.ring == 3);
|
assert(b.ring == 3);
|
||||||
assert(b.position == 3);
|
assert(b.position == 3);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -620,7 +632,7 @@ class WriteBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!WriteBuffer;
|
auto b = defaultAllocator.make!WriteBuffer;
|
||||||
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
|
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
|
||||||
|
|
||||||
b ~= buf;
|
b ~= buf;
|
||||||
@ -630,7 +642,7 @@ class WriteBuffer : Buffer
|
|||||||
b += 4;
|
b += 4;
|
||||||
assert(b.length == 0);
|
assert(b.length == 0);
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -663,7 +675,7 @@ class WriteBuffer : Buffer
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto b = theAllocator.make!WriteBuffer(6);
|
auto b = defaultAllocator.make!WriteBuffer(6);
|
||||||
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
|
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
|
||||||
|
|
||||||
b ~= buf;
|
b ~= buf;
|
||||||
@ -679,7 +691,7 @@ class WriteBuffer : Buffer
|
|||||||
assert(b[0..$] == buf[0..6]);
|
assert(b[0..$] == buf[0..6]);
|
||||||
b += b.length;
|
b += b.length;
|
||||||
|
|
||||||
theAllocator.dispose(b);
|
defaultAllocator.dispose(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +27,7 @@ class SList(T)
|
|||||||
* allocator = The allocator should be used for the element
|
* allocator = The allocator should be used for the element
|
||||||
* allocations.
|
* allocations.
|
||||||
*/
|
*/
|
||||||
this(IAllocator allocator = theAllocator)
|
this(shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
}
|
}
|
||||||
@ -54,14 +54,14 @@ class SList(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
|
|
||||||
l.insertFront(8);
|
l.insertFront(8);
|
||||||
l.insertFront(5);
|
l.insertFront(5);
|
||||||
l.clear();
|
l.clear();
|
||||||
assert(l.empty);
|
assert(l.empty);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,14 +98,14 @@ class SList(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
|
|
||||||
l.insertFront(8);
|
l.insertFront(8);
|
||||||
assert(l.front == 8);
|
assert(l.front == 8);
|
||||||
l.insertFront(9);
|
l.insertFront(9);
|
||||||
assert(l.front == 9);
|
assert(l.front == 9);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,7 +140,7 @@ class SList(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
|
|
||||||
l.insertFront(8);
|
l.insertFront(8);
|
||||||
l.insertFront(9);
|
l.insertFront(9);
|
||||||
@ -148,7 +148,7 @@ class SList(T)
|
|||||||
l.popFront();
|
l.popFront();
|
||||||
assert(l.front == 8);
|
assert(l.front == 8);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,7 +179,7 @@ class SList(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
|
|
||||||
l.insertFront(8);
|
l.insertFront(8);
|
||||||
l.insertFront(5);
|
l.insertFront(5);
|
||||||
@ -189,7 +189,7 @@ class SList(T)
|
|||||||
assert(l.removeFront(3) == 1);
|
assert(l.removeFront(3) == 1);
|
||||||
assert(l.removeFront(3) == 0);
|
assert(l.removeFront(3) == 0);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -235,7 +235,7 @@ class SList(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
|
|
||||||
l.insertFront(5);
|
l.insertFront(5);
|
||||||
l.insertFront(4);
|
l.insertFront(4);
|
||||||
@ -246,7 +246,7 @@ class SList(T)
|
|||||||
assert(i != 1 || e == 4);
|
assert(i != 1 || e == 4);
|
||||||
assert(i != 2 || e == 5);
|
assert(i != 2 || e == 5);
|
||||||
}
|
}
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -265,13 +265,13 @@ class SList(T)
|
|||||||
protected Entry first;
|
protected Entry first;
|
||||||
|
|
||||||
/// Allocator.
|
/// Allocator.
|
||||||
protected IAllocator allocator;
|
protected shared Allocator allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto l = make!(SList!int)(theAllocator);
|
auto l = make!(SList!int)(defaultAllocator);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
l.insertFront(5);
|
l.insertFront(5);
|
||||||
@ -286,7 +286,7 @@ unittest
|
|||||||
}
|
}
|
||||||
assert(i == 3);
|
assert(i == 3);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
private unittest
|
||||||
@ -295,7 +295,7 @@ private unittest
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
auto l = make!(SList!Stuff)(theAllocator);
|
auto l = make!(SList!Stuff)(defaultAllocator);
|
||||||
|
|
||||||
dispose(theAllocator, l);
|
dispose(defaultAllocator, l);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class Queue(T)
|
|||||||
* allocator = The allocator should be used for the element
|
* allocator = The allocator should be used for the element
|
||||||
* allocations.
|
* allocations.
|
||||||
*/
|
*/
|
||||||
this(IAllocator allocator = theAllocator)
|
this(shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ class Queue(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = theAllocator.make!(Queue!int);
|
auto q = defaultAllocator.make!(Queue!int);
|
||||||
|
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
q.insertBack(8);
|
q.insertBack(8);
|
||||||
@ -62,7 +62,7 @@ class Queue(T)
|
|||||||
q.clear();
|
q.clear();
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
|
|
||||||
theAllocator.dispose(q);
|
defaultAllocator.dispose(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,7 +107,7 @@ class Queue(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = make!(Queue!int)(theAllocator);
|
auto q = make!(Queue!int)(defaultAllocator);
|
||||||
|
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
q.insertBack(8);
|
q.insertBack(8);
|
||||||
@ -115,7 +115,7 @@ class Queue(T)
|
|||||||
q.insertBack(9);
|
q.insertBack(9);
|
||||||
assert(q.front == 8);
|
assert(q.front == 8);
|
||||||
|
|
||||||
dispose(theAllocator, q);
|
dispose(defaultAllocator, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,14 +129,14 @@ class Queue(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = make!(Queue!int)(theAllocator);
|
auto q = make!(Queue!int)(defaultAllocator);
|
||||||
int value = 7;
|
int value = 7;
|
||||||
|
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
q.insertBack(value);
|
q.insertBack(value);
|
||||||
assert(!q.empty);
|
assert(!q.empty);
|
||||||
|
|
||||||
dispose(theAllocator, q);
|
dispose(defaultAllocator, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,7 +158,7 @@ class Queue(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = make!(Queue!int)(theAllocator);
|
auto q = make!(Queue!int)(defaultAllocator);
|
||||||
|
|
||||||
q.insertBack(8);
|
q.insertBack(8);
|
||||||
q.insertBack(9);
|
q.insertBack(9);
|
||||||
@ -166,7 +166,7 @@ class Queue(T)
|
|||||||
q.popFront();
|
q.popFront();
|
||||||
assert(q.front == 9);
|
assert(q.front == 9);
|
||||||
|
|
||||||
dispose(theAllocator, q);
|
dispose(defaultAllocator, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,7 +210,7 @@ class Queue(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = theAllocator.make!(Queue!int);
|
auto q = defaultAllocator.make!(Queue!int);
|
||||||
|
|
||||||
size_t j;
|
size_t j;
|
||||||
q.insertBack(5);
|
q.insertBack(5);
|
||||||
@ -240,7 +240,7 @@ class Queue(T)
|
|||||||
assert(j == 3);
|
assert(j == 3);
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
|
|
||||||
dispose(theAllocator, q);
|
dispose(defaultAllocator, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,13 +262,13 @@ class Queue(T)
|
|||||||
protected Entry* rear;
|
protected Entry* rear;
|
||||||
|
|
||||||
/// The allocator.
|
/// The allocator.
|
||||||
protected IAllocator allocator;
|
protected shared Allocator allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto q = theAllocator.make!(Queue!int);
|
auto q = defaultAllocator.make!(Queue!int);
|
||||||
|
|
||||||
q.insertBack(5);
|
q.insertBack(5);
|
||||||
assert(!q.empty);
|
assert(!q.empty);
|
||||||
@ -289,5 +289,5 @@ unittest
|
|||||||
}
|
}
|
||||||
assert(q.empty);
|
assert(q.empty);
|
||||||
|
|
||||||
theAllocator.dispose(q);
|
defaultAllocator.dispose(q);
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ class Vector(T)
|
|||||||
* allocator = The allocator should be used for the element
|
* allocator = The allocator should be used for the element
|
||||||
* allocations.
|
* allocations.
|
||||||
*/
|
*/
|
||||||
this(IAllocator allocator = theAllocator)
|
this(shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
}
|
}
|
||||||
@ -211,18 +211,18 @@ class Vector(T)
|
|||||||
* Params:
|
* Params:
|
||||||
* U = Variadic template for the constructor parameters.
|
* U = Variadic template for the constructor parameters.
|
||||||
* params = Values to initialize the array with. The last parameter can
|
* params = Values to initialize the array with. The last parameter can
|
||||||
* be an allocator, if not, $(D_PSYMBOL theAllocator) is used.
|
* be an allocator, if not, $(D_PSYMBOL defaultAllocator) is used.
|
||||||
*/
|
*/
|
||||||
this(U...)(U params)
|
this(U...)(U params)
|
||||||
{
|
{
|
||||||
static if (isImplicitlyConvertible!(typeof(params[$ - 1]), IAllocator))
|
static if (isImplicitlyConvertible!(typeof(params[$ - 1]), Allocator))
|
||||||
{
|
{
|
||||||
allocator = params[$ - 1];
|
allocator = params[$ - 1];
|
||||||
auto values = params[0 .. $ - 1];
|
auto values = params[0 .. $ - 1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
allocator = theAllocator;
|
allocator = defaultAllocator;
|
||||||
alias values = params;
|
alias values = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(18, 20, 15);
|
auto v = defaultAllocator.make!(Vector!int)(18, 20, 15);
|
||||||
|
|
||||||
v.clear();
|
v.clear();
|
||||||
assert(v.length == 0);
|
assert(v.length == 0);
|
||||||
@ -286,7 +286,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int);
|
auto v = defaultAllocator.make!(Vector!int);
|
||||||
|
|
||||||
v.length = 5;
|
v.length = 5;
|
||||||
assert(v.length == 5);
|
assert(v.length == 5);
|
||||||
@ -337,14 +337,14 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5, 18, 17);
|
auto v = defaultAllocator.make!(Vector!int)(5, 18, 17);
|
||||||
|
|
||||||
assert(v.removeBack(0) == 0);
|
assert(v.removeBack(0) == 0);
|
||||||
assert(v.removeBack(2) == 2);
|
assert(v.removeBack(2) == 2);
|
||||||
assert(v.removeBack(3) == 1);
|
assert(v.removeBack(3) == 1);
|
||||||
assert(v.removeBack(3) == 0);
|
assert(v.removeBack(3) == 0);
|
||||||
|
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,14 +377,14 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = theAllocator.make!(Vector!int)(12, 1, 7);
|
auto v1 = defaultAllocator.make!(Vector!int)(12, 1, 7);
|
||||||
|
|
||||||
v1[] = 3;
|
v1[] = 3;
|
||||||
assert(v1[0] == 3);
|
assert(v1[0] == 3);
|
||||||
assert(v1[1] == 3);
|
assert(v1[1] == 3);
|
||||||
assert(v1[2] == 3);
|
assert(v1[2] == 3);
|
||||||
|
|
||||||
theAllocator.dispose(v1);
|
defaultAllocator.dispose(v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -406,14 +406,14 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(6, 123, 34, 5);
|
auto v = defaultAllocator.make!(Vector!int)(6, 123, 34, 5);
|
||||||
|
|
||||||
assert(v[0] == 6);
|
assert(v[0] == 6);
|
||||||
assert(v[1] == 123);
|
assert(v[1] == 123);
|
||||||
assert(v[2] == 34);
|
assert(v[2] == 34);
|
||||||
assert(v[3] == 5);
|
assert(v[3] == 5);
|
||||||
|
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -435,8 +435,8 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = theAllocator.make!(Vector!int);
|
auto v1 = defaultAllocator.make!(Vector!int);
|
||||||
auto v2 = theAllocator.make!(Vector!int);
|
auto v2 = defaultAllocator.make!(Vector!int);
|
||||||
|
|
||||||
assert(v1 == v2);
|
assert(v1 == v2);
|
||||||
|
|
||||||
@ -453,8 +453,8 @@ class Vector(T)
|
|||||||
v2[1] = 3;
|
v2[1] = 3;
|
||||||
assert(v1 == v2);
|
assert(v1 == v2);
|
||||||
|
|
||||||
theAllocator.dispose(v1);
|
defaultAllocator.dispose(v1);
|
||||||
theAllocator.dispose(v2);
|
defaultAllocator.dispose(v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -495,7 +495,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5, 15, 8);
|
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
foreach (j, ref e; v)
|
foreach (j, ref e; v)
|
||||||
@ -510,7 +510,7 @@ class Vector(T)
|
|||||||
assert(j != 1 || e == 15);
|
assert(j != 1 || e == 15);
|
||||||
assert(j != 2 || e == 8);
|
assert(j != 2 || e == 8);
|
||||||
}
|
}
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -551,7 +551,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5, 15, 8);
|
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
foreach_reverse (j, ref e; v)
|
foreach_reverse (j, ref e; v)
|
||||||
@ -566,7 +566,7 @@ class Vector(T)
|
|||||||
assert(j != 1 || e == 15);
|
assert(j != 1 || e == 15);
|
||||||
assert(j != 0 || e == 5);
|
assert(j != 0 || e == 5);
|
||||||
}
|
}
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -587,7 +587,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5);
|
auto v = defaultAllocator.make!(Vector!int)(5);
|
||||||
|
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
|
|
||||||
@ -595,7 +595,7 @@ class Vector(T)
|
|||||||
v[1] = 15;
|
v[1] = 15;
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
|
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -616,7 +616,7 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5);
|
auto v = defaultAllocator.make!(Vector!int)(5);
|
||||||
|
|
||||||
assert(v.back == 5);
|
assert(v.back == 5);
|
||||||
|
|
||||||
@ -624,7 +624,7 @@ class Vector(T)
|
|||||||
v[1] = 15;
|
v[1] = 15;
|
||||||
assert(v.back == 15);
|
assert(v.back == 15);
|
||||||
|
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -745,8 +745,8 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = theAllocator.make!(Vector!int)(3, 3, 3);
|
auto v1 = defaultAllocator.make!(Vector!int)(3, 3, 3);
|
||||||
auto v2 = theAllocator.make!(Vector!int)(1, 2);
|
auto v2 = defaultAllocator.make!(Vector!int)(1, 2);
|
||||||
|
|
||||||
v1[0..2] = 286;
|
v1[0..2] = 286;
|
||||||
assert(v1[0] == 286);
|
assert(v1[0] == 286);
|
||||||
@ -757,25 +757,25 @@ class Vector(T)
|
|||||||
assert(v2[0] == 286);
|
assert(v2[0] == 286);
|
||||||
assert(v2[1] == 3);
|
assert(v2[1] == 3);
|
||||||
|
|
||||||
theAllocator.dispose(v2);
|
defaultAllocator.dispose(v2);
|
||||||
theAllocator.dispose(v1);
|
defaultAllocator.dispose(v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal representation.
|
/// Internal representation.
|
||||||
protected T[] vector;
|
protected T[] vector;
|
||||||
|
|
||||||
/// The allocator.
|
/// The allocator.
|
||||||
protected IAllocator allocator;
|
protected shared Allocator allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = theAllocator.make!(Vector!int)(5, 15, 8);
|
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
||||||
|
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
assert(v[1] == 15);
|
assert(v[1] == 15);
|
||||||
assert(v.back == 8);
|
assert(v.back == 8);
|
||||||
|
|
||||||
theAllocator.dispose(v);
|
defaultAllocator.dispose(v);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ enum PaddingMode
|
|||||||
ubyte[] pad(ref ubyte[] input,
|
ubyte[] pad(ref ubyte[] input,
|
||||||
in PaddingMode mode,
|
in PaddingMode mode,
|
||||||
in ushort blockSize,
|
in ushort blockSize,
|
||||||
IAllocator allocator = theAllocator)
|
shared Allocator allocator = defaultAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(blockSize > 0 && blockSize <= 256);
|
assert(blockSize > 0 && blockSize <= 256);
|
||||||
@ -86,7 +86,7 @@ body
|
|||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
{ // Zeros
|
{ // Zeros
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
|
|
||||||
pad(input, PaddingMode.zero, 64);
|
pad(input, PaddingMode.zero, 64);
|
||||||
assert(input.length == 64);
|
assert(input.length == 64);
|
||||||
@ -95,10 +95,10 @@ unittest
|
|||||||
assert(input.length == 64);
|
assert(input.length == 64);
|
||||||
assert(input[63] == 0);
|
assert(input[63] == 0);
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
}
|
}
|
||||||
{ // PKCS#7
|
{ // PKCS#7
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
for (ubyte i; i < 40; ++i)
|
for (ubyte i; i < 40; ++i)
|
||||||
{
|
{
|
||||||
input[i] = i;
|
input[i] = i;
|
||||||
@ -140,10 +140,10 @@ unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
}
|
}
|
||||||
{ // ANSI X.923
|
{ // ANSI X.923
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
for (ubyte i; i < 40; ++i)
|
for (ubyte i; i < 40; ++i)
|
||||||
{
|
{
|
||||||
input[i] = i;
|
input[i] = i;
|
||||||
@ -185,7 +185,7 @@ unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ unittest
|
|||||||
ref ubyte[] unpad(ref ubyte[] input,
|
ref ubyte[] unpad(ref ubyte[] input,
|
||||||
in PaddingMode mode,
|
in PaddingMode mode,
|
||||||
in ushort blockSize,
|
in ushort blockSize,
|
||||||
IAllocator allocator = theAllocator)
|
shared Allocator allocator = defaultAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(input.length != 0);
|
assert(input.length != 0);
|
||||||
@ -231,8 +231,8 @@ body
|
|||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
{ // Zeros
|
{ // Zeros
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
auto inputDup = theAllocator.makeArray!ubyte(50);
|
auto inputDup = defaultAllocator.makeArray!ubyte(50);
|
||||||
|
|
||||||
pad(input, PaddingMode.zero, 64);
|
pad(input, PaddingMode.zero, 64);
|
||||||
pad(inputDup, PaddingMode.zero, 64);
|
pad(inputDup, PaddingMode.zero, 64);
|
||||||
@ -240,13 +240,13 @@ unittest
|
|||||||
unpad(input, PaddingMode.zero, 64);
|
unpad(input, PaddingMode.zero, 64);
|
||||||
assert(input == inputDup);
|
assert(input == inputDup);
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
theAllocator.dispose(inputDup);
|
defaultAllocator.dispose(inputDup);
|
||||||
|
|
||||||
}
|
}
|
||||||
{ // PKCS#7
|
{ // PKCS#7
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
auto inputDup = theAllocator.makeArray!ubyte(50);
|
auto inputDup = defaultAllocator.makeArray!ubyte(50);
|
||||||
for (ubyte i; i < 40; ++i)
|
for (ubyte i; i < 40; ++i)
|
||||||
{
|
{
|
||||||
input[i] = i;
|
input[i] = i;
|
||||||
@ -257,12 +257,12 @@ unittest
|
|||||||
unpad(input, PaddingMode.pkcs7, 64);
|
unpad(input, PaddingMode.pkcs7, 64);
|
||||||
assert(input == inputDup);
|
assert(input == inputDup);
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
theAllocator.dispose(inputDup);
|
defaultAllocator.dispose(inputDup);
|
||||||
}
|
}
|
||||||
{ // ANSI X.923
|
{ // ANSI X.923
|
||||||
auto input = theAllocator.makeArray!ubyte(50);
|
auto input = defaultAllocator.makeArray!ubyte(50);
|
||||||
auto inputDup = theAllocator.makeArray!ubyte(50);
|
auto inputDup = defaultAllocator.makeArray!ubyte(50);
|
||||||
for (ubyte i; i < 40; ++i)
|
for (ubyte i; i < 40; ++i)
|
||||||
{
|
{
|
||||||
input[i] = i;
|
input[i] = i;
|
||||||
@ -273,7 +273,7 @@ unittest
|
|||||||
unpad(input, PaddingMode.pkcs7, 64);
|
unpad(input, PaddingMode.pkcs7, 64);
|
||||||
assert(input == inputDup);
|
assert(input == inputDup);
|
||||||
|
|
||||||
theAllocator.dispose(input);
|
defaultAllocator.dispose(input);
|
||||||
theAllocator.dispose(inputDup);
|
defaultAllocator.dispose(inputDup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,16 @@ module tanya.math.mp;
|
|||||||
import std.algorithm.iteration;
|
import std.algorithm.iteration;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.experimental.allocator;
|
|
||||||
import std.math;
|
import std.math;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
import tanya.memory.allocator;
|
import tanya.memory;
|
||||||
import tanya.memory.types;
|
|
||||||
|
|
||||||
struct Integer
|
struct Integer
|
||||||
{
|
{
|
||||||
private RefCounted!(ubyte[]) rep;
|
private RefCounted!(ubyte[]) rep;
|
||||||
private bool sign;
|
private bool sign;
|
||||||
|
private shared Allocator allocator;
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
@ -34,10 +33,11 @@ struct Integer
|
|||||||
* Creates a multiple precision integer.
|
* Creates a multiple precision integer.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
|
* T = Value type.
|
||||||
* value = Initial value.
|
* value = Initial value.
|
||||||
* allocator = Allocator.
|
* allocator = Allocator.
|
||||||
*/
|
*/
|
||||||
this(T)(in T value, IAllocator allocator = theAllocator)
|
this(T)(in T value, shared Allocator allocator = defaultAllocator)
|
||||||
if (isIntegral!T)
|
if (isIntegral!T)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@ -47,21 +47,30 @@ struct Integer
|
|||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
|
|
||||||
immutable size = calculateSizeFromInt(value);
|
T absolute = value;
|
||||||
|
immutable size = calculateSizeFromInt(absolute);
|
||||||
allocator.resizeArray(rep, size);
|
allocator.resizeArray(rep, size);
|
||||||
assignInt(value);
|
assignInt(absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
|
{
|
||||||
{
|
{
|
||||||
auto h = Integer(79);
|
auto h = Integer(79);
|
||||||
assert(h.length == 1);
|
assert(h.length == 1);
|
||||||
assert(h.rep[0] == 79);
|
assert(h.rep[0] == 79);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
auto h = Integer(-2);
|
||||||
|
assert(h.length == 1);
|
||||||
|
assert(h.rep[0] == 2);
|
||||||
|
assert(h.sign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
this(in Integer value, IAllocator allocator = theAllocator)
|
this(in Integer value, shared Allocator allocator = defaultAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(allocator !is null);
|
assert(allocator !is null);
|
||||||
@ -76,21 +85,35 @@ struct Integer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
this(IAllocator allocator)
|
this(shared Allocator allocator)
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
rep = RefCounted!(ubyte[])(allocator);
|
rep = RefCounted!(ubyte[])(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out the minimum amount of space this value will take
|
* Figures out the minimum amount of space this value will take
|
||||||
* up in bytes.
|
* up in bytes. Set the sign.
|
||||||
*/
|
*/
|
||||||
pragma(inline, true)
|
private ubyte calculateSizeFromInt(T)(ref T value)
|
||||||
private ubyte calculateSizeFromInt(in ulong value)
|
pure nothrow @safe @nogc
|
||||||
const pure nothrow @safe @nogc
|
in
|
||||||
|
{
|
||||||
|
static assert(isIntegral!T);
|
||||||
|
}
|
||||||
|
body
|
||||||
{
|
{
|
||||||
ubyte size = ulong.sizeof;
|
ubyte size = ulong.sizeof;
|
||||||
|
|
||||||
|
static if (isSigned!T)
|
||||||
|
{
|
||||||
|
sign = value < 0 ? true : false;
|
||||||
|
value = abs(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sign = false;
|
||||||
|
}
|
||||||
for (ulong mask = 0xff00000000000000; mask >= 0xff; mask >>= 8)
|
for (ulong mask = 0xff00000000000000; mask >= 0xff; mask >>= 8)
|
||||||
{
|
{
|
||||||
if (value & mask)
|
if (value & mask)
|
||||||
@ -107,40 +130,42 @@ struct Integer
|
|||||||
* (up to the first 0 byte) and copy it into the internal
|
* (up to the first 0 byte) and copy it into the internal
|
||||||
* representation in big-endian format.
|
* representation in big-endian format.
|
||||||
*/
|
*/
|
||||||
pragma(inline, true)
|
private void assignInt(in ulong value)
|
||||||
private void assignInt(T)(ref in T value)
|
|
||||||
pure nothrow @safe @nogc
|
pure nothrow @safe @nogc
|
||||||
in
|
|
||||||
{
|
|
||||||
static assert(isIntegral!T);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
{
|
||||||
uint mask = 0xff, shift;
|
uint mask = 0xff, shift;
|
||||||
immutable absolute = abs(value);
|
|
||||||
|
|
||||||
sign = value < 0 ? true : false;
|
|
||||||
for (auto i = length; i; --i)
|
for (auto i = length; i; --i)
|
||||||
{
|
{
|
||||||
rep[i - 1] = cast(ubyte) ((absolute & mask) >> shift);
|
rep[i - 1] = cast(ubyte) ((value & mask) >> shift);
|
||||||
mask <<= 8;
|
mask <<= 8;
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a new value.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Value type.
|
||||||
|
* value = Value.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
ref Integer opAssign(T)(in T value)
|
ref Integer opAssign(T)(in T value)
|
||||||
if (isIntegral!T)
|
if (isIntegral!T)
|
||||||
{
|
{
|
||||||
immutable size = calculateSizeFromInt(value);
|
T absolute = value;
|
||||||
|
immutable size = calculateSizeFromInt(absolute);
|
||||||
|
|
||||||
checkAllocator();
|
checkAllocator();
|
||||||
allocator.resizeArray(rep.get, size);
|
allocator.resizeArray(rep.get, size);
|
||||||
assignInt(value);
|
assignInt(absolute);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
ref Integer opAssign(in Integer value)
|
ref Integer opAssign(in Integer value)
|
||||||
{
|
{
|
||||||
checkAllocator();
|
checkAllocator();
|
||||||
@ -251,23 +276,11 @@ struct Integer
|
|||||||
assert(h1 > h2);
|
assert(h1 > h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void add(in ref RefCounted!(ubyte[]) h)
|
||||||
* Assignment operators with another $(D_PSYMBOL Integer).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* op = Operation.
|
|
||||||
* h = The second integer.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD this).
|
|
||||||
*/
|
|
||||||
ref Integer opOpAssign(string op)(in Integer h)
|
|
||||||
if (op == "+")
|
|
||||||
{
|
{
|
||||||
uint sum;
|
uint sum;
|
||||||
uint carry = 0;
|
uint carry = 0;
|
||||||
|
|
||||||
checkAllocator();
|
|
||||||
|
|
||||||
// Adding h2 to h1. If h2 is > h1 to begin with, resize h1
|
// Adding h2 to h1. If h2 is > h1 to begin with, resize h1
|
||||||
|
|
||||||
if (h.length > length)
|
if (h.length > length)
|
||||||
@ -286,7 +299,7 @@ struct Integer
|
|||||||
if (j)
|
if (j)
|
||||||
{
|
{
|
||||||
--j;
|
--j;
|
||||||
sum = rep[i] + h.rep[j] + carry;
|
sum = rep[i] + h[j] + carry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -305,36 +318,15 @@ struct Integer
|
|||||||
tmp[0] = 0x01;
|
tmp[0] = 0x01;
|
||||||
rep = tmp;
|
rep = tmp;
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
private void subtract(in ref RefCounted!(ubyte[]) h)
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto h1 = Integer(1019);
|
|
||||||
|
|
||||||
auto h2 = Integer(3337);
|
|
||||||
h1 += h2;
|
|
||||||
assert(h1.rep == [0x11, 0x04]);
|
|
||||||
|
|
||||||
h2 = 2_147_483_647;
|
|
||||||
h1 += h2;
|
|
||||||
assert(h1.rep == [0x80, 0x00, 0x11, 0x03]);
|
|
||||||
|
|
||||||
h1 += h2;
|
|
||||||
assert(h1.rep == [0x01, 0x00, 0x00, 0x11, 0x02]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ditto.
|
|
||||||
ref Integer opOpAssign(string op)(in Integer h)
|
|
||||||
if (op == "-")
|
|
||||||
{
|
{
|
||||||
auto i = rep.length;
|
auto i = rep.length;
|
||||||
auto j = h.rep.length;
|
auto j = h.length;
|
||||||
uint borrow = 0;
|
uint borrow = 0;
|
||||||
|
|
||||||
checkAllocator();
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int difference;
|
int difference;
|
||||||
@ -343,7 +335,7 @@ struct Integer
|
|||||||
if (j)
|
if (j)
|
||||||
{
|
{
|
||||||
--j;
|
--j;
|
||||||
difference = rep[i] - h.rep[j] - borrow;
|
difference = rep[i] - h[j] - borrow;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -371,11 +363,49 @@ struct Integer
|
|||||||
{
|
{
|
||||||
allocator.resizeArray(rep, 0);
|
allocator.resizeArray(rep, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assignment operators with another $(D_PSYMBOL Integer).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* op = Operation.
|
||||||
|
* h = The second integer.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref Integer opOpAssign(string op)(in Integer h)
|
||||||
|
if ((op == "+") || (op == "-"))
|
||||||
|
{
|
||||||
|
checkAllocator();
|
||||||
|
static if (op == "+")
|
||||||
|
{
|
||||||
|
add(h.rep);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subtract(h.rep);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
private unittest
|
||||||
unittest
|
{
|
||||||
|
auto h1 = Integer(1019);
|
||||||
|
|
||||||
|
auto h2 = Integer(3337);
|
||||||
|
h1 += h2;
|
||||||
|
assert(h1.rep == [0x11, 0x04]);
|
||||||
|
|
||||||
|
h2 = 2_147_483_647;
|
||||||
|
h1 += h2;
|
||||||
|
assert(h1.rep == [0x80, 0x00, 0x11, 0x03]);
|
||||||
|
|
||||||
|
h1 += h2;
|
||||||
|
assert(h1.rep == [0x01, 0x00, 0x00, 0x11, 0x02]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unittest
|
||||||
{
|
{
|
||||||
auto h1 = Integer(4294967295);
|
auto h1 = Integer(4294967295);
|
||||||
auto h2 = Integer(4294967295);
|
auto h2 = Integer(4294967295);
|
||||||
@ -417,8 +447,7 @@ struct Integer
|
|||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
--i;
|
--i, --j;
|
||||||
--j;
|
|
||||||
immutable oldCarry = carry;
|
immutable oldCarry = carry;
|
||||||
carry = rep[i] >> delta;
|
carry = rep[i] >> delta;
|
||||||
rep[j] = cast(ubyte) ((rep[i] << bit) | oldCarry);
|
rep[j] = cast(ubyte) ((rep[i] << bit) | oldCarry);
|
||||||
@ -546,6 +575,11 @@ struct Integer
|
|||||||
/// Ditto.
|
/// Ditto.
|
||||||
ref Integer opOpAssign(string op)(in Integer h)
|
ref Integer opOpAssign(string op)(in Integer h)
|
||||||
if ((op == "/") || (op == "%"))
|
if ((op == "/") || (op == "%"))
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(h.length > 0, "Division by zero.");
|
||||||
|
}
|
||||||
|
body
|
||||||
{
|
{
|
||||||
checkAllocator();
|
checkAllocator();
|
||||||
|
|
||||||
@ -715,25 +749,23 @@ struct Integer
|
|||||||
assert(h2.rep[0] == ~cast(ubyte) 79);
|
assert(h2.rep[0] == ~cast(ubyte) 79);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void decrement()
|
||||||
* Increment/decrement.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* op = Operation.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD this).
|
|
||||||
*/
|
|
||||||
ref Integer opUnary(string op)()
|
|
||||||
if ((op == "++") || (op == "--"))
|
|
||||||
{
|
{
|
||||||
checkAllocator();
|
immutable size = rep.get.retro.countUntil!((const ref a) => a != 0);
|
||||||
|
if (rep[0] == 1)
|
||||||
if (op == "++" || sign || length == 0)
|
|
||||||
{
|
{
|
||||||
static if (op == "--")
|
allocator.resizeArray(rep, rep.length - 1);
|
||||||
{
|
rep[0 .. $] = typeof(rep[0]).max;
|
||||||
sign = true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--rep[$ - size - 1];
|
||||||
|
rep[$ - size .. $] = typeof(rep[0]).max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void increment()
|
||||||
|
{
|
||||||
auto size = rep
|
auto size = rep
|
||||||
.get
|
.get
|
||||||
.retro
|
.retro
|
||||||
@ -750,24 +782,43 @@ struct Integer
|
|||||||
}
|
}
|
||||||
rep[$ - size .. $] = 0;
|
rep[$ - size .. $] = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/**
|
||||||
|
* Increment/decrement.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* op = Operation.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref Integer opUnary(string op)()
|
||||||
|
if ((op == "++") || (op == "--"))
|
||||||
{
|
{
|
||||||
immutable size = rep.get.retro.countUntil!((const ref a) => a != 0);
|
checkAllocator();
|
||||||
if (rep[0] == 1)
|
|
||||||
|
static if (op == "++")
|
||||||
{
|
{
|
||||||
allocator.resizeArray(rep, rep.length - 1);
|
if (sign)
|
||||||
rep[0 .. $] = typeof(rep[0]).max;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
--rep[$ - size - 1];
|
decrement();
|
||||||
rep[$ - size .. $] = typeof(rep[0]).max;
|
if (length == 0)
|
||||||
}
|
|
||||||
if (rep.length == 0)
|
|
||||||
{
|
{
|
||||||
sign = false;
|
sign = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sign)
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decrement();
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,7 +854,17 @@ struct Integer
|
|||||||
|
|
||||||
--h;
|
--h;
|
||||||
assert(h.rep == [0xff, 0xff]);
|
assert(h.rep == [0xff, 0xff]);
|
||||||
|
|
||||||
|
h = -2;
|
||||||
|
++h;
|
||||||
|
assert(h.rep == [0x01]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin StructAllocator;
|
private void checkAllocator() nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
if (allocator is null)
|
||||||
|
{
|
||||||
|
allocator = defaultAllocator;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,214 +10,42 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory.allocator;
|
module tanya.memory.allocator;
|
||||||
|
|
||||||
import std.algorithm.mutation;
|
|
||||||
import std.experimental.allocator;
|
|
||||||
import std.typecons;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class implementing a basic allocator.
|
* Abstract class implementing a basic allocator.
|
||||||
*/
|
*/
|
||||||
abstract class Allocator : IAllocator
|
interface Allocator
|
||||||
{
|
{
|
||||||
/**
|
@nogc:
|
||||||
* Not supported.
|
@property uint alignment() const shared pure nothrow @safe;
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD false).
|
|
||||||
*/
|
|
||||||
bool deallocateAll() const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not supported.
|
* Allocates $(D_PARAM size) bytes of memory.
|
||||||
*
|
*
|
||||||
* Returns $(D_PSYMBOL Ternary.unknown).
|
|
||||||
*/
|
|
||||||
Ternary empty() const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return Ternary.unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* b = Memory block.
|
|
||||||
*
|
|
||||||
* Returns: $(D_PSYMBOL Ternary.unknown).
|
|
||||||
*/
|
|
||||||
Ternary owns(void[] b) const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return Ternary.unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* p = Pointer to a memory block.
|
|
||||||
* result = Full block allocated.
|
|
||||||
*
|
|
||||||
* Returns: $(D_PSYMBOL Ternary.unknown).
|
|
||||||
*/
|
|
||||||
Ternary resolveInternalPointer(void* p, ref void[] result)
|
|
||||||
const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return Ternary.unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Params:
|
* Params:
|
||||||
* size = Amount of memory to allocate.
|
* size = Amount of memory to allocate.
|
||||||
*
|
*
|
||||||
* Returns: The good allocation size that guarantees zero internal
|
* Returns: The pointer to the new allocated memory.
|
||||||
* fragmentation.
|
|
||||||
*/
|
*/
|
||||||
size_t goodAllocSize(size_t s)
|
void[] allocate(size_t size, TypeInfo ti = null) shared nothrow @safe;
|
||||||
{
|
|
||||||
auto rem = s % alignment;
|
|
||||||
return rem ? s + alignment - rem : s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not supported.
|
* Deallocates a memory block.
|
||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD null).
|
* Params:
|
||||||
|
* p = A pointer to the memory block to be freed.
|
||||||
*
|
*
|
||||||
|
* Returns: Whether the deallocation was successful.
|
||||||
*/
|
*/
|
||||||
void[] allocateAll() const @nogc @safe pure nothrow
|
bool deallocate(void[] p) shared nothrow @safe;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not supported.
|
* Increases or decreases the size of a memory block.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* b = Block to be expanded.
|
* p = A pointer to the memory block.
|
||||||
* s = New size.
|
* size = Size of the reallocated block.
|
||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD false).
|
* Returns: Whether the reallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool expand(ref void[] b, size_t s) const @nogc @safe pure nothrow
|
bool reallocate(ref void[] p, size_t size) shared nothrow @safe;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* n = Amount of memory to allocate.
|
|
||||||
* a = Alignment.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD null).
|
|
||||||
*/
|
|
||||||
void[] alignedAllocate(size_t n, uint a) const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* n = Amount of memory to allocate.
|
|
||||||
* a = Alignment.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD false).
|
|
||||||
*/
|
|
||||||
bool alignedReallocate(ref void[] b, size_t size, uint alignment)
|
|
||||||
const @nogc @safe pure nothrow
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* init = The value to fill the new part of the array with if it becomes
|
|
||||||
* larger.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD true) upon success, $(D_KEYWORD false) if memory could
|
|
||||||
* not be reallocated. In the latter
|
|
||||||
*/
|
|
||||||
bool resizeArray(T)(IAllocator allocator,
|
|
||||||
ref T[] array,
|
|
||||||
in size_t length,
|
|
||||||
T init = T.init)
|
|
||||||
{
|
|
||||||
void[] buf = array;
|
|
||||||
immutable oldLength = array.length;
|
|
||||||
|
|
||||||
if (!allocator.reallocate(buf, length * T.sizeof))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
array = cast(T[]) buf;
|
|
||||||
if (oldLength < length)
|
|
||||||
{
|
|
||||||
array[oldLength .. $].uninitializedFill(init);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
int[] p;
|
|
||||||
|
|
||||||
theAllocator.resizeArray(p, 20);
|
|
||||||
assert(p.length == 20);
|
|
||||||
|
|
||||||
theAllocator.resizeArray(p, 30);
|
|
||||||
assert(p.length == 30);
|
|
||||||
|
|
||||||
theAllocator.resizeArray(p, 10);
|
|
||||||
assert(p.length == 10);
|
|
||||||
|
|
||||||
theAllocator.resizeArray(p, 0);
|
|
||||||
assert(p is null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mixin to get around the impossibility to define a default constructor for
|
|
||||||
* structs. It can be used for the structs that don't disable the default
|
|
||||||
* constructor and don't wan't to force passing the allocator each time to
|
|
||||||
* the constructor.
|
|
||||||
*
|
|
||||||
* It defines the private property `allocator`, a constructor that accepts only
|
|
||||||
* an allocator instance and the method `checkAllocator` that checks if an
|
|
||||||
* allocator is set and sets it to ` $(D_PSYMBOL theAllocator) if not.
|
|
||||||
*
|
|
||||||
* `checkAllocator` should be used at beginning of functions that
|
|
||||||
* allocate/free memory.
|
|
||||||
*/
|
|
||||||
mixin template StructAllocator()
|
|
||||||
{
|
|
||||||
private IAllocator allocator;
|
|
||||||
|
|
||||||
this(IAllocator allocator) pure nothrow @safe @nogc
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(allocator !is null);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
this.allocator = allocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline, true)
|
|
||||||
private void checkAllocator() nothrow @safe @nogc
|
|
||||||
{
|
|
||||||
if (allocator is null)
|
|
||||||
{
|
|
||||||
allocator = theAllocator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,7 @@ else version (Windows)
|
|||||||
*/
|
*/
|
||||||
class MmapPool : Allocator
|
class MmapPool : Allocator
|
||||||
{
|
{
|
||||||
@disable this();
|
@nogc:
|
||||||
|
|
||||||
shared static this()
|
shared static this()
|
||||||
{
|
{
|
||||||
version (Posix)
|
version (Posix)
|
||||||
@ -83,7 +82,7 @@ class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: The pointer to the new allocated memory.
|
* Returns: The pointer to the new allocated memory.
|
||||||
*/
|
*/
|
||||||
void[] allocate(size_t size, TypeInfo ti = null) @nogc @trusted nothrow
|
void[] allocate(size_t size, TypeInfo ti = null) shared nothrow @trusted
|
||||||
{
|
{
|
||||||
if (!size)
|
if (!size)
|
||||||
{
|
{
|
||||||
@ -101,7 +100,7 @@ class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe nothrow unittest
|
@safe nothrow unittest
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
|
|
||||||
@ -119,7 +118,7 @@ class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Data the block points to or $(D_KEYWORD null).
|
* Returns: Data the block points to or $(D_KEYWORD null).
|
||||||
*/
|
*/
|
||||||
private void* findBlock(size_t size) @nogc nothrow
|
private void* findBlock(size_t size) shared nothrow
|
||||||
{
|
{
|
||||||
Block block1;
|
Block block1;
|
||||||
RegionLoop: for (auto r = head; r !is null; r = r.next)
|
RegionLoop: for (auto r = head; r !is null; r = r.next)
|
||||||
@ -177,7 +176,7 @@ class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the deallocation was successful.
|
* Returns: Whether the deallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool deallocate(void[] p) @nogc @trusted nothrow
|
bool deallocate(void[] p) shared nothrow @trusted
|
||||||
{
|
{
|
||||||
if (p is null)
|
if (p is null)
|
||||||
{
|
{
|
||||||
@ -217,7 +216,7 @@ class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe nothrow unittest
|
@safe nothrow unittest
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
|
|
||||||
@ -233,7 +232,7 @@ class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the reallocation was successful.
|
* Returns: Whether the reallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool reallocate(ref void[] p, size_t size) @nogc @trusted nothrow
|
bool reallocate(ref void[] p, size_t size) shared nothrow @trusted
|
||||||
{
|
{
|
||||||
void[] reallocP;
|
void[] reallocP;
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
nothrow unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
||||||
@ -301,7 +300,7 @@ class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
||||||
*/
|
*/
|
||||||
static @property ref MmapPool instance() @nogc @trusted nothrow
|
static @property ref shared(MmapPool) instance() nothrow @trusted
|
||||||
{
|
{
|
||||||
if (instance_ is null)
|
if (instance_ is null)
|
||||||
{
|
{
|
||||||
@ -312,7 +311,7 @@ class MmapPool : Allocator
|
|||||||
if (data !is null)
|
if (data !is null)
|
||||||
{
|
{
|
||||||
data[0..instanceSize] = typeid(MmapPool).initializer[];
|
data[0..instanceSize] = typeid(MmapPool).initializer[];
|
||||||
instance_ = cast(MmapPool) data;
|
instance_ = cast(shared MmapPool) data;
|
||||||
instance_.head = head;
|
instance_.head = head;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +319,7 @@ class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc @safe nothrow unittest
|
@safe nothrow unittest
|
||||||
{
|
{
|
||||||
assert(instance is instance);
|
assert(instance is instance);
|
||||||
}
|
}
|
||||||
@ -335,7 +334,7 @@ class MmapPool : Allocator
|
|||||||
* Returns: A pointer to the data.
|
* Returns: A pointer to the data.
|
||||||
*/
|
*/
|
||||||
private static void* initializeRegion(size_t size,
|
private static void* initializeRegion(size_t size,
|
||||||
ref Region head) @nogc nothrow
|
ref Region head) nothrow
|
||||||
{
|
{
|
||||||
immutable regionSize = calculateRegionSize(size);
|
immutable regionSize = calculateRegionSize(size);
|
||||||
|
|
||||||
@ -408,7 +407,7 @@ class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
private void* initializeRegion(size_t size) @nogc nothrow
|
private void* initializeRegion(size_t size) shared nothrow
|
||||||
{
|
{
|
||||||
return initializeRegion(size, head);
|
return initializeRegion(size, head);
|
||||||
}
|
}
|
||||||
@ -421,7 +420,7 @@ class MmapPool : Allocator
|
|||||||
*/
|
*/
|
||||||
pragma(inline)
|
pragma(inline)
|
||||||
private static immutable(size_t) addAlignment(size_t x)
|
private static immutable(size_t) addAlignment(size_t x)
|
||||||
@nogc @safe pure nothrow
|
@safe pure nothrow
|
||||||
out (result)
|
out (result)
|
||||||
{
|
{
|
||||||
assert(result > 0);
|
assert(result > 0);
|
||||||
@ -439,7 +438,7 @@ class MmapPool : Allocator
|
|||||||
*/
|
*/
|
||||||
pragma(inline)
|
pragma(inline)
|
||||||
private static immutable(size_t) calculateRegionSize(size_t x)
|
private static immutable(size_t) calculateRegionSize(size_t x)
|
||||||
@nogc @safe pure nothrow
|
@safe pure nothrow
|
||||||
out (result)
|
out (result)
|
||||||
{
|
{
|
||||||
assert(result > 0);
|
assert(result > 0);
|
||||||
@ -450,13 +449,13 @@ class MmapPool : Allocator
|
|||||||
return x / pageSize * pageSize + pageSize;
|
return x / pageSize * pageSize + pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property uint alignment() const @nogc @safe pure nothrow
|
@property uint alignment() shared const pure nothrow @safe
|
||||||
{
|
{
|
||||||
return alignment_;
|
return alignment_;
|
||||||
}
|
}
|
||||||
private enum alignment_ = 8;
|
private enum alignment_ = 8;
|
||||||
|
|
||||||
private static MmapPool instance_;
|
private static shared MmapPool instance_;
|
||||||
|
|
||||||
private shared static immutable size_t pageSize;
|
private shared static immutable size_t pageSize;
|
||||||
|
|
||||||
|
@ -10,6 +10,75 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory;
|
module tanya.memory;
|
||||||
|
|
||||||
|
import std.algorithm.mutation;
|
||||||
public import std.experimental.allocator;
|
public import std.experimental.allocator;
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
public import tanya.memory.types;
|
public import tanya.memory.types;
|
||||||
|
|
||||||
|
shared Allocator allocator;
|
||||||
|
|
||||||
|
shared static this() nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
import tanya.memory.mmappool;
|
||||||
|
allocator = MmapPool.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void defaultAllocator(shared(Allocator) allocator) nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
.allocator = 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.
|
||||||
|
* init = The value to fill the new part of the array with if it becomes
|
||||||
|
* larger.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) upon success, $(D_KEYWORD false) if memory could
|
||||||
|
* not be reallocated. In the latter
|
||||||
|
*/
|
||||||
|
bool resizeArray(T)(shared Allocator allocator,
|
||||||
|
ref T[] array,
|
||||||
|
in size_t length,
|
||||||
|
T init = T.init)
|
||||||
|
{
|
||||||
|
void[] buf = array;
|
||||||
|
immutable oldLength = array.length;
|
||||||
|
|
||||||
|
if (!allocator.reallocate(buf, length * T.sizeof))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
array = cast(T[]) buf;
|
||||||
|
if (oldLength < length)
|
||||||
|
{
|
||||||
|
array[oldLength .. $].uninitializedFill(init);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
@ -37,13 +37,15 @@ struct RefCounted(T)
|
|||||||
private T* payload;
|
private T* payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint *counter;
|
private uint counter;
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
assert(counter is null || allocator !is null);
|
assert(counter == 0 || allocator !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private shared Allocator allocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes ownership over $(D_PARAM value), setting the counter to 1.
|
* Takes ownership over $(D_PARAM value), setting the counter to 1.
|
||||||
*
|
*
|
||||||
@ -54,20 +56,29 @@ struct RefCounted(T)
|
|||||||
|
|
||||||
* Precondition: $(D_INLINECODE allocator !is null)
|
* Precondition: $(D_INLINECODE allocator !is null)
|
||||||
*/
|
*/
|
||||||
this(T value, IAllocator allocator = theAllocator)
|
this(T value, shared Allocator allocator = defaultAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(allocator !is null);
|
assert(allocator !is null);
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this(allocator);
|
||||||
initialize();
|
static if (!isReference!T)
|
||||||
move(value, get);
|
{
|
||||||
|
payload = cast(T*) allocator.allocate(stateSize!T).ptr;
|
||||||
|
move(value, *payload);
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
|
else if (value !is null)
|
||||||
|
{
|
||||||
|
move(value, payload);
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
this(IAllocator allocator)
|
this(shared Allocator allocator) pure nothrow @safe @nogc
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(allocator !is null);
|
assert(allocator !is null);
|
||||||
@ -77,28 +88,6 @@ struct RefCounted(T)
|
|||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates the internal storage.
|
|
||||||
*/
|
|
||||||
private void initialize()
|
|
||||||
{
|
|
||||||
static if (isReference!T)
|
|
||||||
{
|
|
||||||
counter = allocator.make!uint(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Allocate for the counter and the payload together.
|
|
||||||
auto p = allocator.allocate(uint.sizeof + T.sizeof);
|
|
||||||
if (p is null)
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
counter = emplace(cast(uint*) p.ptr, 1);
|
|
||||||
payload = cast(T*) p[uint.sizeof .. $].ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the reference counter by one.
|
* Increases the reference counter by one.
|
||||||
*/
|
*/
|
||||||
@ -106,7 +95,7 @@ struct RefCounted(T)
|
|||||||
{
|
{
|
||||||
if (isInitialized)
|
if (isInitialized)
|
||||||
{
|
{
|
||||||
++(*counter);
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,15 +106,14 @@ struct RefCounted(T)
|
|||||||
*/
|
*/
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
if (!isInitialized || (--(*counter)))
|
if (isInitialized && !--counter)
|
||||||
|
{
|
||||||
|
static if (isReference!T)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
allocator.dispose(payload);
|
allocator.dispose(payload);
|
||||||
payload = null;
|
payload = null;
|
||||||
|
}
|
||||||
allocator.dispose(counter);
|
}
|
||||||
counter = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +123,7 @@ struct RefCounted(T)
|
|||||||
* If it is the last reference of the previously owned object,
|
* If it is the last reference of the previously owned object,
|
||||||
* it will be destroyed.
|
* it will be destroyed.
|
||||||
*
|
*
|
||||||
* If the allocator wasn't set before, $(D_PSYMBOL theAllocator) will
|
* If the allocator wasn't set before, $(D_PSYMBOL defaultAllocator) will
|
||||||
* be used. If you need a different allocator, create a new
|
* be used. If you need a different allocator, create a new
|
||||||
* $(D_PSYMBOL RefCounted).
|
* $(D_PSYMBOL RefCounted).
|
||||||
*
|
*
|
||||||
@ -144,21 +132,18 @@ struct RefCounted(T)
|
|||||||
*/
|
*/
|
||||||
ref T opAssign(T rhs)
|
ref T opAssign(T rhs)
|
||||||
{
|
{
|
||||||
checkAllocator();
|
if (allocator is null)
|
||||||
if (isInitialized)
|
|
||||||
{
|
{
|
||||||
|
allocator = defaultAllocator;
|
||||||
|
}
|
||||||
static if (isReference!T)
|
static if (isReference!T)
|
||||||
{
|
{
|
||||||
if (!--(*counter))
|
counter == 1 ? allocator.dispose(payload) : --counter;
|
||||||
|
}
|
||||||
|
else if (!isInitialized)
|
||||||
{
|
{
|
||||||
allocator.dispose(payload);
|
payload = cast(T*) allocator.allocate(stateSize!T).ptr;
|
||||||
*counter = 1;
|
counter = 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
initialize();
|
|
||||||
}
|
}
|
||||||
move(rhs, get);
|
move(rhs, get);
|
||||||
return get;
|
return get;
|
||||||
@ -212,7 +197,7 @@ struct RefCounted(T)
|
|||||||
*/
|
*/
|
||||||
@property uint count() const pure nothrow @safe @nogc
|
@property uint count() const pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
return counter is null ? 0 : *counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,11 +205,9 @@ struct RefCounted(T)
|
|||||||
*/
|
*/
|
||||||
@property bool isInitialized() const pure nothrow @safe @nogc
|
@property bool isInitialized() const pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
return counter !is null;
|
return counter != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin StructAllocator;
|
|
||||||
|
|
||||||
alias get this;
|
alias get this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,9 +230,11 @@ version (unittest)
|
|||||||
|
|
||||||
struct B
|
struct B
|
||||||
{
|
{
|
||||||
|
int prop;
|
||||||
@disable this();
|
@disable this();
|
||||||
this(int param1)
|
this(int param1)
|
||||||
{
|
{
|
||||||
|
prop = param1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,7 +254,7 @@ unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto arr = theAllocator.makeArray!ubyte(2);
|
auto arr = defaultAllocator.makeArray!ubyte(2);
|
||||||
{
|
{
|
||||||
auto a = S(arr);
|
auto a = S(arr);
|
||||||
assert(a.member.count == 1);
|
assert(a.member.count == 1);
|
||||||
@ -288,7 +273,7 @@ unittest
|
|||||||
private unittest
|
private unittest
|
||||||
{
|
{
|
||||||
uint destroyed;
|
uint destroyed;
|
||||||
auto a = theAllocator.make!A(destroyed);
|
auto a = defaultAllocator.make!A(destroyed);
|
||||||
|
|
||||||
assert(destroyed == 0);
|
assert(destroyed == 0);
|
||||||
{
|
{
|
||||||
@ -323,6 +308,7 @@ private unittest
|
|||||||
static assert(!is(typeof(cast(int) (RefCounted!A()))));
|
static assert(!is(typeof(cast(int) (RefCounted!A()))));
|
||||||
|
|
||||||
static assert(is(RefCounted!B));
|
static assert(is(RefCounted!B));
|
||||||
|
static assert(is(RefCounted!A));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -341,40 +327,26 @@ private unittest
|
|||||||
*
|
*
|
||||||
* Returns: Newly created $(D_PSYMBOL RefCounted!T).
|
* Returns: Newly created $(D_PSYMBOL RefCounted!T).
|
||||||
*/
|
*/
|
||||||
RefCounted!T refCounted(T, A...)(IAllocator allocator, auto ref A args)
|
RefCounted!T refCounted(T, A...)(shared Allocator allocator, auto ref A args)
|
||||||
if (!is(T == interface) && !isAbstractClass!T)
|
if (!is(T == interface) && !isAbstractClass!T)
|
||||||
{
|
{
|
||||||
auto rc = typeof(return)(allocator);
|
static if (isReference!T)
|
||||||
|
|
||||||
immutable toAllocate = max(stateSize!T, 1) + uint.sizeof;
|
|
||||||
auto p = allocator.allocate(toAllocate);
|
|
||||||
if (p is null)
|
|
||||||
{
|
{
|
||||||
onOutOfMemoryError();
|
return typeof(return)(allocator.make!T(args), allocator);
|
||||||
}
|
|
||||||
scope (failure)
|
|
||||||
{
|
|
||||||
allocator.deallocate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.counter = emplace(cast(uint*) p.ptr, 1);
|
|
||||||
|
|
||||||
static if (is(T == class))
|
|
||||||
{
|
|
||||||
rc.payload = emplace!T(p[uint.sizeof .. $], args);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc.payload = emplace(cast(T*) p[uint.sizeof .. $].ptr, args);
|
auto rc = typeof(return)(allocator);
|
||||||
}
|
rc.counter = 1;
|
||||||
|
rc.payload = allocator.make!T(args);
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto rc = theAllocator.refCounted!int(5);
|
auto rc = defaultAllocator.refCounted!int(5);
|
||||||
assert(rc.count == 1);
|
assert(rc.count == 1);
|
||||||
|
|
||||||
void func(RefCounted!int param)
|
void func(RefCounted!int param)
|
||||||
@ -395,7 +367,21 @@ unittest
|
|||||||
|
|
||||||
private unittest
|
private unittest
|
||||||
{
|
{
|
||||||
static assert(!is(theAllocator.refCounted!A));
|
struct E
|
||||||
static assert(!is(typeof(theAllocator.refCounted!B())));
|
{
|
||||||
static assert(is(typeof(theAllocator.refCounted!B(5))));
|
}
|
||||||
|
static assert(is(typeof(defaultAllocator.refCounted!bool(false))));
|
||||||
|
static assert(is(typeof(defaultAllocator.refCounted!B(5))));
|
||||||
|
static assert(!is(typeof(defaultAllocator.refCounted!B())));
|
||||||
|
|
||||||
|
static assert(is(typeof(defaultAllocator.refCounted!E())));
|
||||||
|
static assert(!is(typeof(defaultAllocator.refCounted!E(5))));
|
||||||
|
{
|
||||||
|
auto rc = defaultAllocator.refCounted!B(3);
|
||||||
|
assert(rc.get.prop == 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto rc = defaultAllocator.refCounted!E();
|
||||||
|
assert(rc.isInitialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ else version (Windows)
|
|||||||
|
|
||||||
if (result == SOCKET_ERROR && !wouldHaveBlocked)
|
if (result == SOCKET_ERROR && !wouldHaveBlocked)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to receive");
|
throw defaultAllocator.make!SocketException("Unable to receive");
|
||||||
}
|
}
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
@ -282,7 +282,7 @@ else version (Windows)
|
|||||||
if (result == FALSE && !wouldHaveBlocked)
|
if (result == FALSE && !wouldHaveBlocked)
|
||||||
{
|
{
|
||||||
disconnected_ = true;
|
disconnected_ = true;
|
||||||
throw theAllocator.make!SocketException("Unable to receive");
|
throw defaultAllocator.make!SocketException("Unable to receive");
|
||||||
}
|
}
|
||||||
if (lpNumber == 0)
|
if (lpNumber == 0)
|
||||||
{
|
{
|
||||||
@ -324,7 +324,7 @@ else version (Windows)
|
|||||||
if (result == SOCKET_ERROR && !wouldHaveBlocked)
|
if (result == SOCKET_ERROR && !wouldHaveBlocked)
|
||||||
{
|
{
|
||||||
disconnected_ = true;
|
disconnected_ = true;
|
||||||
throw theAllocator.make!SocketException("Unable to send");
|
throw defaultAllocator.make!SocketException("Unable to send");
|
||||||
}
|
}
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ else version (Windows)
|
|||||||
if (result == FALSE && !wouldHaveBlocked)
|
if (result == FALSE && !wouldHaveBlocked)
|
||||||
{
|
{
|
||||||
disconnected_ = true;
|
disconnected_ = true;
|
||||||
throw theAllocator.make!SocketException("Unable to receive");
|
throw defaultAllocator.make!SocketException("Unable to receive");
|
||||||
}
|
}
|
||||||
return lpNumber;
|
return lpNumber;
|
||||||
}
|
}
|
||||||
@ -396,7 +396,8 @@ else version (Windows)
|
|||||||
NULL);
|
NULL);
|
||||||
if (!result == SOCKET_ERROR)
|
if (!result == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to retrieve an accept extension function pointer");
|
throw make!SocketException(defaultAllocator,
|
||||||
|
"Unable to retrieve an accept extension function pointer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +417,7 @@ else version (Windows)
|
|||||||
auto socket = cast(socket_t) socket(addressFamily, SOCK_STREAM, 0);
|
auto socket = cast(socket_t) socket(addressFamily, SOCK_STREAM, 0);
|
||||||
if (socket == socket_t.init)
|
if (socket == socket_t.init)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to create socket");
|
throw defaultAllocator.make!SocketException("Unable to create socket");
|
||||||
}
|
}
|
||||||
scope (failure)
|
scope (failure)
|
||||||
{
|
{
|
||||||
@ -426,7 +427,8 @@ else version (Windows)
|
|||||||
overlapped.handle = cast(HANDLE) socket;
|
overlapped.handle = cast(HANDLE) socket;
|
||||||
overlapped.event = OverlappedSocketEvent.accept;
|
overlapped.event = OverlappedSocketEvent.accept;
|
||||||
overlapped.buffer.len = (sockaddr_in.sizeof + 16) * 2;
|
overlapped.buffer.len = (sockaddr_in.sizeof + 16) * 2;
|
||||||
overlapped.buffer.buf = theAllocator.makeArray!char(overlapped.buffer.len).ptr;
|
overlapped.buffer.buf = makeArray!char(defaultAllocator,
|
||||||
|
overlapped.buffer.len).ptr;
|
||||||
|
|
||||||
// We don't want to get any data now, but only start to accept the connections
|
// We don't want to get any data now, but only start to accept the connections
|
||||||
BOOL result = acceptExtension(handle_,
|
BOOL result = acceptExtension(handle_,
|
||||||
@ -439,7 +441,7 @@ else version (Windows)
|
|||||||
&overlapped.overlapped);
|
&overlapped.overlapped);
|
||||||
if (result == FALSE && !wouldHaveBlocked)
|
if (result == FALSE && !wouldHaveBlocked)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to accept socket connection");
|
throw defaultAllocator.make!SocketException("Unable to accept socket connection");
|
||||||
}
|
}
|
||||||
return result == TRUE;
|
return result == TRUE;
|
||||||
}
|
}
|
||||||
@ -459,13 +461,14 @@ else version (Windows)
|
|||||||
{
|
{
|
||||||
scope (exit)
|
scope (exit)
|
||||||
{
|
{
|
||||||
theAllocator.dispose(overlapped.buffer.buf[0..overlapped.buffer.len]);
|
defaultAllocator.dispose(overlapped.buffer.buf[0..overlapped.buffer.len]);
|
||||||
}
|
}
|
||||||
auto socket = theAllocator.make!OverlappedConnectedSocket(cast(socket_t) overlapped.handle,
|
auto socket = make!OverlappedConnectedSocket(defaultAllocator,
|
||||||
|
cast(socket_t) overlapped.handle,
|
||||||
addressFamily);
|
addressFamily);
|
||||||
scope (failure)
|
scope (failure)
|
||||||
{
|
{
|
||||||
theAllocator.dispose(socket);
|
defaultAllocator.dispose(socket);
|
||||||
}
|
}
|
||||||
socket.setOption(SocketOptionLevel.SOCKET,
|
socket.setOption(SocketOptionLevel.SOCKET,
|
||||||
cast(SocketOption) SO_UPDATE_ACCEPT_CONTEXT,
|
cast(SocketOption) SO_UPDATE_ACCEPT_CONTEXT,
|
||||||
@ -737,7 +740,7 @@ abstract class Socket
|
|||||||
result.ptr,
|
result.ptr,
|
||||||
&length) == SOCKET_ERROR)
|
&length) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to get socket option");
|
throw defaultAllocator.make!SocketException("Unable to get socket option");
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -797,7 +800,7 @@ abstract class Socket
|
|||||||
value.ptr,
|
value.ptr,
|
||||||
cast(uint) value.length) == SOCKET_ERROR)
|
cast(uint) value.length) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to set socket option");
|
throw defaultAllocator.make!SocketException("Unable to set socket option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +868,8 @@ abstract class Socket
|
|||||||
}
|
}
|
||||||
if (fl == SOCKET_ERROR)
|
if (fl == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to set socket blocking");
|
throw make!SocketException(defaultAllocator,
|
||||||
|
"Unable to set socket blocking");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else version (Windows)
|
else version (Windows)
|
||||||
@ -873,7 +877,8 @@ abstract class Socket
|
|||||||
uint num = !yes;
|
uint num = !yes;
|
||||||
if (ioctlsocket(handle_, FIONBIO, &num) == SOCKET_ERROR)
|
if (ioctlsocket(handle_, FIONBIO, &num) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to set socket blocking");
|
throw make!SocketException(defaultAllocator,
|
||||||
|
"Unable to set socket blocking");
|
||||||
}
|
}
|
||||||
blocking_ = yes;
|
blocking_ = yes;
|
||||||
}
|
}
|
||||||
@ -942,7 +947,7 @@ abstract class Socket
|
|||||||
{
|
{
|
||||||
if (.listen(handle_, backlog) == SOCKET_ERROR)
|
if (.listen(handle_, backlog) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to listen on socket");
|
throw defaultAllocator.make!SocketException("Unable to listen on socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +997,7 @@ class StreamSocket : Socket, ConnectionOrientedSocket
|
|||||||
auto handle = cast(socket_t) socket(af, SOCK_STREAM, 0);
|
auto handle = cast(socket_t) socket(af, SOCK_STREAM, 0);
|
||||||
if (handle == socket_t.init)
|
if (handle == socket_t.init)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to create socket");
|
throw defaultAllocator.make!SocketException("Unable to create socket");
|
||||||
}
|
}
|
||||||
super(handle, af);
|
super(handle, af);
|
||||||
}
|
}
|
||||||
@ -1009,7 +1014,7 @@ class StreamSocket : Socket, ConnectionOrientedSocket
|
|||||||
{
|
{
|
||||||
if (.bind(handle_, address.name, address.length) == SOCKET_ERROR)
|
if (.bind(handle_, address.name, address.length) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!SocketException("Unable to bind socket");
|
throw defaultAllocator.make!SocketException("Unable to bind socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,10 +1053,11 @@ class StreamSocket : Socket, ConnectionOrientedSocket
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
throw theAllocator.make!SocketException("Unable to accept socket connection");
|
throw make!SocketException(defaultAllocator,
|
||||||
|
"Unable to accept socket connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newSocket = theAllocator.make!ConnectedSocket(sock, addressFamily);
|
auto newSocket = defaultAllocator.make!ConnectedSocket(sock, addressFamily);
|
||||||
|
|
||||||
version (linux)
|
version (linux)
|
||||||
{ // Blocking mode already set
|
{ // Blocking mode already set
|
||||||
@ -1066,7 +1072,7 @@ class StreamSocket : Socket, ConnectionOrientedSocket
|
|||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
theAllocator.dispose(newSocket);
|
defaultAllocator.dispose(newSocket);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1162,7 +1168,7 @@ class ConnectedSocket : Socket, ConnectionOrientedSocket
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
disconnected_ = true;
|
disconnected_ = true;
|
||||||
throw theAllocator.make!SocketException("Unable to receive");
|
throw defaultAllocator.make!SocketException("Unable to receive");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1199,7 +1205,7 @@ class ConnectedSocket : Socket, ConnectionOrientedSocket
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
throw theAllocator.make!SocketException("Unable to send");
|
throw defaultAllocator.make!SocketException("Unable to send");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1242,18 +1248,19 @@ class InternetAddress : Address
|
|||||||
{
|
{
|
||||||
if (getaddrinfoPointer is null || freeaddrinfoPointer is null)
|
if (getaddrinfoPointer is null || freeaddrinfoPointer is null)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!AddressException("Address info lookup is not available on this system");
|
throw make!AddressException(defaultAllocator,
|
||||||
|
"Address info lookup is not available on this system");
|
||||||
}
|
}
|
||||||
addrinfo* ai_res;
|
addrinfo* ai_res;
|
||||||
port_ = port;
|
port_ = port;
|
||||||
|
|
||||||
// Make C-string from host.
|
// Make C-string from host.
|
||||||
char[] node = theAllocator.makeArray!char(host.length + 1);
|
char[] node = defaultAllocator.makeArray!char(host.length + 1);
|
||||||
node[0.. $ - 1] = host;
|
node[0.. $ - 1] = host;
|
||||||
node[$ - 1] = '\0';
|
node[$ - 1] = '\0';
|
||||||
scope (exit)
|
scope (exit)
|
||||||
{
|
{
|
||||||
theAllocator.dispose(node);
|
defaultAllocator.dispose(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert port to a C-string.
|
// Convert port to a C-string.
|
||||||
@ -1278,7 +1285,7 @@ class InternetAddress : Address
|
|||||||
auto ret = getaddrinfoPointer(node.ptr, servicePointer, null, &ai_res);
|
auto ret = getaddrinfoPointer(node.ptr, servicePointer, null, &ai_res);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!AddressException("Address info lookup failed");
|
throw defaultAllocator.make!AddressException("Address info lookup failed");
|
||||||
}
|
}
|
||||||
scope (exit)
|
scope (exit)
|
||||||
{
|
{
|
||||||
@ -1292,7 +1299,7 @@ class InternetAddress : Address
|
|||||||
}
|
}
|
||||||
if (ai_res.ai_family != AddressFamily.INET && ai_res.ai_family != AddressFamily.INET6)
|
if (ai_res.ai_family != AddressFamily.INET && ai_res.ai_family != AddressFamily.INET6)
|
||||||
{
|
{
|
||||||
throw theAllocator.make!AddressException("Wrong address family");
|
throw defaultAllocator.make!AddressException("Wrong address family");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1352,7 +1359,8 @@ bool wouldHaveBlocked() nothrow @trusted @nogc
|
|||||||
}
|
}
|
||||||
else version (Windows)
|
else version (Windows)
|
||||||
{
|
{
|
||||||
return WSAGetLastError() == ERROR_IO_PENDING || WSAGetLastError() == EWOULDBLOCK
|
return WSAGetLastError() == ERROR_IO_PENDING
|
||||||
|
|| WSAGetLastError() == EWOULDBLOCK
|
||||||
|| WSAGetLastError() == ERROR_IO_INCOMPLETE;
|
|| WSAGetLastError() == ERROR_IO_INCOMPLETE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,7 +702,7 @@ struct URL(U = string)
|
|||||||
{
|
{
|
||||||
if (!parsePort(value[pos..$]))
|
if (!parsePort(value[pos..$]))
|
||||||
{
|
{
|
||||||
throw theAllocator.make!URIException("Failed to parse port");
|
throw defaultAllocator.make!URIException("Failed to parse port");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto ParsePath;
|
goto ParsePath;
|
||||||
@ -751,7 +751,7 @@ struct URL(U = string)
|
|||||||
else if (pos == 0 && parsePort(value[pos..$]))
|
else if (pos == 0 && parsePort(value[pos..$]))
|
||||||
{
|
{
|
||||||
// An URL shouldn't begin with a port number
|
// An URL shouldn't begin with a port number
|
||||||
throw theAllocator.make!URIException("URL begins with port");
|
throw defaultAllocator.make!URIException("URL begins with port");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -808,7 +808,7 @@ struct URL(U = string)
|
|||||||
{
|
{
|
||||||
pass = null;
|
pass = null;
|
||||||
}
|
}
|
||||||
throw make!URIException(theAllocator,
|
throw make!URIException(defaultAllocator,
|
||||||
"Restricted characters in user information");
|
"Restricted characters in user information");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,7 +844,7 @@ struct URL(U = string)
|
|||||||
{
|
{
|
||||||
pass = null;
|
pass = null;
|
||||||
}
|
}
|
||||||
throw theAllocator.make!URIException("Invalid port");
|
throw defaultAllocator.make!URIException("Invalid port");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -866,7 +866,7 @@ struct URL(U = string)
|
|||||||
{
|
{
|
||||||
pass = null;
|
pass = null;
|
||||||
}
|
}
|
||||||
throw theAllocator.make!URIException("Invalid host");
|
throw defaultAllocator.make!URIException("Invalid host");
|
||||||
}
|
}
|
||||||
|
|
||||||
host = value[start..pos];
|
host = value[start..pos];
|
||||||
@ -912,8 +912,8 @@ struct URL(U = string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
if (scheme !is null)
|
if (scheme !is null)
|
||||||
{
|
{
|
||||||
scheme = null;
|
scheme = null;
|
||||||
@ -942,7 +942,7 @@ struct URL(U = string)
|
|||||||
{
|
{
|
||||||
fragment = null;
|
fragment = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to parse and set the port.
|
* Attempts to parse and set the port.
|
||||||
@ -1106,7 +1106,7 @@ URL parseURL(U)(in U source)
|
|||||||
return URL!U(source);
|
return URL!U(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ditto */
|
/// Ditto.
|
||||||
string parseURL(string T, U)(in U source)
|
string parseURL(string T, U)(in U source)
|
||||||
if ((T == "scheme"
|
if ((T == "scheme"
|
||||||
|| T =="host"
|
|| T =="host"
|
||||||
@ -1120,7 +1120,7 @@ string parseURL(string T, U)(in U source)
|
|||||||
return mixin("ret." ~ T);
|
return mixin("ret." ~ T);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ditto */
|
/// Ditto.
|
||||||
ushort parseURL(string T, U)(in U source)
|
ushort parseURL(string T, U)(in U source)
|
||||||
if (T == "port" && isSomeString!U)
|
if (T == "port" && isSomeString!U)
|
||||||
{
|
{
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.random;
|
module tanya.random;
|
||||||
|
|
||||||
import tanya.memory;
|
import std.experimental.allocator;
|
||||||
import std.digest.sha;
|
import std.digest.sha;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
import tanya.memory;
|
||||||
|
|
||||||
/// Block size of entropy accumulator (SHA-512).
|
/// Block size of entropy accumulator (SHA-512).
|
||||||
enum blockSize = 64;
|
enum blockSize = 64;
|
||||||
@ -148,13 +149,13 @@ version (linux)
|
|||||||
/**
|
/**
|
||||||
* Pseudorandom number generator.
|
* Pseudorandom number generator.
|
||||||
* ---
|
* ---
|
||||||
* auto entropy = theAllocator.make!Entropy;
|
* auto entropy = defaultAllocator.make!Entropy();
|
||||||
*
|
*
|
||||||
* ubyte[blockSize] output;
|
* ubyte[blockSize] output;
|
||||||
*
|
*
|
||||||
* output = entropy.random;
|
* output = entropy.random;
|
||||||
*
|
*
|
||||||
* theAllocator.finalize(entropy);
|
* defaultAllocator.finalize(entropy);
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
class Entropy
|
class Entropy
|
||||||
@ -175,7 +176,7 @@ class Entropy
|
|||||||
* allocator = Allocator to allocate entropy sources available on the
|
* allocator = Allocator to allocate entropy sources available on the
|
||||||
* system.
|
* system.
|
||||||
*/
|
*/
|
||||||
this(size_t maxSources = 20, IAllocator allocator = theAllocator)
|
this(size_t maxSources = 20, shared Allocator allocator = defaultAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(maxSources > 0 && maxSources <= ubyte.max);
|
assert(maxSources > 0 && maxSources <= ubyte.max);
|
||||||
|
Loading…
Reference in New Issue
Block a user