Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
e77a499fa2 | |||
54bcec216e | |||
fbbdb36853 | |||
b795267e75 | |||
81cbb96d45 | |||
467335460e | |||
dc3b083097 | |||
16c5fa12df | |||
9bf8754711 | |||
760cea163d | |||
03c40ecace | |||
9c70e9a058 | |||
5ae20512af | |||
d30de300d6 | |||
464a0fecbb | |||
84d6e207c5 | |||
af942116e4 | |||
7ee4af9e79 | |||
9876d9245c | |||
bd2b88f16e |
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
# D
|
# D
|
||||||
.dub
|
.dub
|
||||||
|
dub.selections.json
|
||||||
|
|
||||||
__test__*__
|
__test__*__
|
||||||
__test__*__.core
|
__test__*__.core
|
||||||
/tanya-test-*
|
/tanya-test-*
|
||||||
|
@ -7,7 +7,8 @@ os:
|
|||||||
language: d
|
language: d
|
||||||
|
|
||||||
d:
|
d:
|
||||||
- dmd-2.078.2
|
- dmd-2.079.0
|
||||||
|
- dmd-2.078.3
|
||||||
- dmd-2.077.1
|
- dmd-2.077.1
|
||||||
- dmd-2.076.1
|
- dmd-2.076.1
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ addons:
|
|||||||
- gcc-multilib
|
- gcc-multilib
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- if [ "$PS1" = '(dmd-2.078.2)' ]; then
|
- if [ "$PS1" = '(dmd-2.079.0)' ]; then
|
||||||
export UNITTEST="unittest-cov";
|
export UNITTEST="unittest-cov";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -149,7 +149,8 @@ There are more containers in the `tanya.container` package.
|
|||||||
|
|
||||||
| DMD | GCC |
|
| DMD | GCC |
|
||||||
|:-------:|:--------------:|
|
|:-------:|:--------------:|
|
||||||
| 2.078.2 | *gdc-5* branch |
|
| 2.079.0 | *master* |
|
||||||
|
| 2.078.3 | |
|
||||||
| 2.077.1 | |
|
| 2.077.1 | |
|
||||||
| 2.076.1 | |
|
| 2.076.1 | |
|
||||||
|
|
||||||
@ -168,7 +169,7 @@ Deprecated features are removed after one release that includes these deprecatio
|
|||||||
|
|
||||||
## Further characteristics
|
## Further characteristics
|
||||||
|
|
||||||
* Tanya is a native D library without any external dependencies.
|
* Tanya is a native D library
|
||||||
|
|
||||||
* Tanya is cross-platform. The development happens on a 64-bit Linux, but it
|
* Tanya is cross-platform. The development happens on a 64-bit Linux, but it
|
||||||
is being tested on Windows and FreeBSD as well.
|
is being tested on Windows and FreeBSD as well.
|
||||||
|
10
appveyor.yml
10
appveyor.yml
@ -4,10 +4,16 @@ os: Visual Studio 2015
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.078.2
|
DVersion: 2.079.0
|
||||||
arch: x64
|
arch: x64
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.078.2
|
DVersion: 2.079.0
|
||||||
|
arch: x86
|
||||||
|
- DC: dmd
|
||||||
|
DVersion: 2.078.3
|
||||||
|
arch: x64
|
||||||
|
- DC: dmd
|
||||||
|
DVersion: 2.078.3
|
||||||
arch: x86
|
arch: x86
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.077.1
|
DVersion: 2.077.1
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
|
|
||||||
// logl.
|
// logl.
|
||||||
.globl _D5tanya4math8nbtheory2lnFNaNbNiNfeZe
|
.globl _D5tanya4math8nbtheory9__T2lnTeZ2lnFNaNbNiNfeZe
|
||||||
.type _D5tanya4math8nbtheory2lnFNaNbNiNfeZe, @function
|
.type _D5tanya4math8nbtheory9__T2lnTeZ2lnFNaNbNiNfeZe, @function
|
||||||
|
|
||||||
_D5tanya4math8nbtheory2lnFNaNbNiNfeZe:
|
_D5tanya4math8nbtheory9__T2lnTeZ2lnFNaNbNiNfeZe:
|
||||||
fldln2 // Put lb(e) onto the FPU stack
|
fldln2 // Put lb(e) onto the FPU stack
|
||||||
fldt 8(%rsp) // Put the argument onto the FPU stack
|
fldt 8(%rsp) // Put the argument onto the FPU stack
|
||||||
fyl2x // %st1 * lb(%st0)
|
fyl2x // %st1 * lb(%st0)
|
||||||
@ -13,10 +13,10 @@ _D5tanya4math8nbtheory2lnFNaNbNiNfeZe:
|
|||||||
|
|
||||||
|
|
||||||
// log.
|
// log.
|
||||||
.globl _D5tanya4math8nbtheory2lnFNaNbNiNfdZd
|
.globl _D5tanya4math8nbtheory9__T2lnTdZ2lnFNaNbNiNfdZd
|
||||||
.type _D5tanya4math8nbtheory2lnFNaNbNiNfdZd, @function
|
.type _D5tanya4math8nbtheory9__T2lnTdZ2lnFNaNbNiNfdZd, @function
|
||||||
|
|
||||||
_D5tanya4math8nbtheory2lnFNaNbNiNfdZd:
|
_D5tanya4math8nbtheory9__T2lnTdZ2lnFNaNbNiNfdZd:
|
||||||
movsd %xmm0, -8(%rsp) // Put the argument onto the stack
|
movsd %xmm0, -8(%rsp) // Put the argument onto the stack
|
||||||
|
|
||||||
fldln2 // Put lb(e) onto the FPU stack
|
fldln2 // Put lb(e) onto the FPU stack
|
||||||
@ -31,10 +31,10 @@ _D5tanya4math8nbtheory2lnFNaNbNiNfdZd:
|
|||||||
|
|
||||||
|
|
||||||
// logf.
|
// logf.
|
||||||
.globl _D5tanya4math8nbtheory2lnFNaNbNiNffZf
|
.globl _D5tanya4math8nbtheory9__T2lnTfZ2lnFNaNbNiNffZf
|
||||||
.type _D5tanya4math8nbtheory2lnFNaNbNiNffZf, @function
|
.type _D5tanya4math8nbtheory9__T2lnTfZ2lnFNaNbNiNffZf, @function
|
||||||
|
|
||||||
_D5tanya4math8nbtheory2lnFNaNbNiNffZf:
|
_D5tanya4math8nbtheory9__T2lnTfZ2lnFNaNbNiNffZf:
|
||||||
movss %xmm0, -4(%rsp) // Put the argument onto the stack
|
movss %xmm0, -4(%rsp) // Put the argument onto the stack
|
||||||
|
|
||||||
fldln2 // Put lb(e) onto the FPU stack
|
fldln2 // Put lb(e) onto the FPU stack
|
||||||
|
7
dub.json
7
dub.json
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
"targetType": "library",
|
"targetType": "library",
|
||||||
|
|
||||||
|
"dependencies-linux": {
|
||||||
|
"mir-linux-kernel": "~>1.0.0",
|
||||||
|
},
|
||||||
|
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "library",
|
"name": "library",
|
||||||
@ -28,5 +32,6 @@
|
|||||||
"lflags": ["arch/tanya.a"],
|
"lflags": ["arch/tanya.a"],
|
||||||
"versions": ["TanyaNative"]
|
"versions": ["TanyaNative"]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"libs-windows": ["advapi32"]
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ import tanya.async.transport;
|
|||||||
import tanya.async.watcher;
|
import tanya.async.watcher;
|
||||||
import tanya.container.array;
|
import tanya.container.array;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
extern (C) nothrow @nogc
|
extern (C) nothrow @nogc
|
||||||
@ -56,7 +55,7 @@ final class EpollLoop : SelectorLoop
|
|||||||
throw defaultAllocator.make!BadLoopException("epoll initialization failed");
|
throw defaultAllocator.make!BadLoopException("epoll initialization failed");
|
||||||
}
|
}
|
||||||
super();
|
super();
|
||||||
events = Array!epoll_event(maxEvents, MmapPool.instance);
|
events = Array!epoll_event(maxEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +27,6 @@ import tanya.async.transport;
|
|||||||
import tanya.async.watcher;
|
import tanya.async.watcher;
|
||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
import tanya.sys.windows.winbase;
|
import tanya.sys.windows.winbase;
|
||||||
|
|
||||||
@ -57,8 +56,8 @@ final class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
this(OverlappedConnectedSocket socket) @nogc
|
this(OverlappedConnectedSocket socket) @nogc
|
||||||
{
|
{
|
||||||
super(socket);
|
super(socket);
|
||||||
output = ReadBuffer!ubyte(8192, 1024, MmapPool.instance);
|
output = ReadBuffer!ubyte(8192, 1024);
|
||||||
input = WriteBuffer!ubyte(8192, MmapPool.instance);
|
input = WriteBuffer!ubyte(8192);
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,8 +116,7 @@ final class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
/**
|
/**
|
||||||
* Switches the protocol.
|
* Switches the protocol.
|
||||||
*
|
*
|
||||||
* The protocol is deallocated by the event loop, it should currently be
|
* The protocol is deallocated by the event loop.
|
||||||
* allocated with $(D_PSYMBOL MmapPool).
|
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* protocol = Application protocol.
|
* protocol = Application protocol.
|
||||||
@ -150,20 +148,20 @@ final class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
SocketState overlapped;
|
SocketState overlapped;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
overlapped = MmapPool.instance.make!SocketState;
|
overlapped = defaultAllocator.make!SocketState;
|
||||||
socket.beginSend(input[], overlapped);
|
socket.beginSend(input[], overlapped);
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
defaultAllocator.dispose(overlapped);
|
||||||
MmapPool.instance.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
protocol.disconnected(exception);
|
protocol.disconnected(exception);
|
||||||
MmapPool.instance.dispose(protocol_);
|
defaultAllocator.dispose(protocol_);
|
||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
@ -221,12 +219,12 @@ final class IOCPLoop : Loop
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
overlapped = MmapPool.instance.make!SocketState;
|
overlapped = defaultAllocator.make!SocketState;
|
||||||
socket.beginAccept(overlapped);
|
socket.beginAccept(overlapped);
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
defaultAllocator.dispose(overlapped);
|
||||||
defaultAllocator.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -250,12 +248,12 @@ final class IOCPLoop : Loop
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
overlapped = MmapPool.instance.make!SocketState;
|
overlapped = defaultAllocator.make!SocketState;
|
||||||
transport.socket.beginReceive(transport.output[], overlapped);
|
transport.socket.beginReceive(transport.output[], overlapped);
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
defaultAllocator.dispose(overlapped);
|
||||||
defaultAllocator.dispose(e);
|
defaultAllocator.dispose(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -302,7 +300,7 @@ final class IOCPLoop : Loop
|
|||||||
assert(overlapped !is null);
|
assert(overlapped !is null);
|
||||||
scope (failure)
|
scope (failure)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(overlapped);
|
defaultAllocator.dispose(overlapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (overlapped.event)
|
switch (overlapped.event)
|
||||||
@ -315,7 +313,7 @@ final class IOCPLoop : Loop
|
|||||||
assert(listener !is null);
|
assert(listener !is null);
|
||||||
|
|
||||||
auto socket = listener.endAccept(overlapped);
|
auto socket = listener.endAccept(overlapped);
|
||||||
auto transport = MmapPool.instance.make!StreamTransport(socket);
|
auto transport = defaultAllocator.make!StreamTransport(socket);
|
||||||
|
|
||||||
connection.incoming.enqueue(transport);
|
connection.incoming.enqueue(transport);
|
||||||
|
|
||||||
@ -330,8 +328,8 @@ final class IOCPLoop : Loop
|
|||||||
|
|
||||||
if (!transport.active)
|
if (!transport.active)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(transport);
|
defaultAllocator.dispose(transport);
|
||||||
MmapPool.instance.dispose(overlapped);
|
defaultAllocator.dispose(overlapped);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ import tanya.async.transport;
|
|||||||
import tanya.async.watcher;
|
import tanya.async.watcher;
|
||||||
import tanya.container.array;
|
import tanya.container.array;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args) pure nothrow @nogc
|
void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args) pure nothrow @nogc
|
||||||
@ -146,8 +145,8 @@ final class KqueueLoop : SelectorLoop
|
|||||||
throw make!BadLoopException(defaultAllocator,
|
throw make!BadLoopException(defaultAllocator,
|
||||||
"kqueue initialization failed");
|
"kqueue initialization failed");
|
||||||
}
|
}
|
||||||
events = Array!kevent_t(64, MmapPool.instance);
|
events = Array!kevent_t(64);
|
||||||
changes = Array!kevent_t(64, MmapPool.instance);
|
changes = Array!kevent_t(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,6 @@ import tanya.async.watcher;
|
|||||||
import tanya.container.array;
|
import tanya.container.array;
|
||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,8 +64,8 @@ package class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
{
|
{
|
||||||
super(socket);
|
super(socket);
|
||||||
this.loop = loop;
|
this.loop = loop;
|
||||||
output = ReadBuffer!ubyte(8192, 1024, MmapPool.instance);
|
output = ReadBuffer!ubyte(8192, 1024);
|
||||||
input = WriteBuffer!ubyte(8192, MmapPool.instance);
|
input = WriteBuffer!ubyte(8192);
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +106,7 @@ package class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
/**
|
/**
|
||||||
* Switches the protocol.
|
* Switches the protocol.
|
||||||
*
|
*
|
||||||
* The protocol is deallocated by the event loop, it should currently be
|
* The protocol is deallocated by the event loop.
|
||||||
* allocated with $(D_PSYMBOL MmapPool).
|
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* protocol = Application protocol.
|
* protocol = Application protocol.
|
||||||
@ -163,7 +161,7 @@ package class StreamTransport : SocketWatcher, DuplexTransport, SocketTransport
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
protocol.disconnected(exception);
|
protocol.disconnected(exception);
|
||||||
MmapPool.instance.dispose(protocol_);
|
defaultAllocator.dispose(protocol_);
|
||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
@ -220,7 +218,7 @@ abstract class SelectorLoop : Loop
|
|||||||
this() @nogc
|
this() @nogc
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
connections = Array!SocketWatcher(maxEvents, MmapPool.instance);
|
connections = Array!SocketWatcher(maxEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() @nogc
|
~this() @nogc
|
||||||
@ -231,7 +229,7 @@ abstract class SelectorLoop : Loop
|
|||||||
// created by the user and should be freed by himself.
|
// created by the user and should be freed by himself.
|
||||||
if (cast(StreamTransport) connection !is null)
|
if (cast(StreamTransport) connection !is null)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(connection);
|
defaultAllocator.dispose(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,7 +385,7 @@ abstract class SelectorLoop : Loop
|
|||||||
}
|
}
|
||||||
if (transport is null)
|
if (transport is null)
|
||||||
{
|
{
|
||||||
transport = MmapPool.instance.make!StreamTransport(this, client);
|
transport = defaultAllocator.make!StreamTransport(this, client);
|
||||||
connections[client.handle] = transport;
|
connections[client.handle] = transport;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -78,7 +78,6 @@ import tanya.async.watcher;
|
|||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.container.queue;
|
import tanya.container.queue;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
version (DisableBackends)
|
version (DisableBackends)
|
||||||
@ -189,7 +188,7 @@ abstract class Loop
|
|||||||
*/
|
*/
|
||||||
this() @nogc
|
this() @nogc
|
||||||
{
|
{
|
||||||
pendings = Queue!Watcher(MmapPool.instance);
|
pendings = Queue!Watcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,7 +198,7 @@ abstract class Loop
|
|||||||
{
|
{
|
||||||
foreach (w; pendings)
|
foreach (w; pendings)
|
||||||
{
|
{
|
||||||
MmapPool.instance.dispose(w);
|
defaultAllocator.dispose(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,16 +383,16 @@ class BadLoopException : Exception
|
|||||||
}
|
}
|
||||||
version (Epoll)
|
version (Epoll)
|
||||||
{
|
{
|
||||||
defaultLoop_ = MmapPool.instance.make!EpollLoop;
|
defaultLoop_ = defaultAllocator.make!EpollLoop;
|
||||||
}
|
}
|
||||||
else version (IOCP)
|
else version (IOCP)
|
||||||
{
|
{
|
||||||
defaultLoop_ = MmapPool.instance.make!IOCPLoop;
|
defaultLoop_ = defaultAllocator.make!IOCPLoop;
|
||||||
}
|
}
|
||||||
else version (Kqueue)
|
else version (Kqueue)
|
||||||
{
|
{
|
||||||
import tanya.async.event.kqueue;
|
import tanya.async.event.kqueue;
|
||||||
defaultLoop_ = MmapPool.instance.make!KqueueLoop;
|
defaultLoop_ = defaultAllocator.make!KqueueLoop;
|
||||||
}
|
}
|
||||||
return defaultLoop_;
|
return defaultLoop_;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,7 @@ interface DuplexTransport : ReadTransport, WriteTransport
|
|||||||
/**
|
/**
|
||||||
* Switches the protocol.
|
* Switches the protocol.
|
||||||
*
|
*
|
||||||
* The protocol is deallocated by the event loop, it should currently be
|
* The protocol is deallocated by the event loop.
|
||||||
* allocated with $(D_PSYMBOL MmapPool).
|
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* protocol = Application protocol.
|
* protocol = Application protocol.
|
||||||
|
@ -22,7 +22,6 @@ import tanya.async.transport;
|
|||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.container.queue;
|
import tanya.container.queue;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,7 +102,7 @@ class ConnectionWatcher : SocketWatcher
|
|||||||
this(Socket socket) @nogc
|
this(Socket socket) @nogc
|
||||||
{
|
{
|
||||||
super(socket);
|
super(socket);
|
||||||
incoming = Queue!DuplexTransport(MmapPool.instance);
|
incoming = Queue!DuplexTransport();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +111,7 @@ class ConnectionWatcher : SocketWatcher
|
|||||||
*/
|
*/
|
||||||
void setProtocol(P : Protocol)() @nogc
|
void setProtocol(P : Protocol)() @nogc
|
||||||
{
|
{
|
||||||
this.protocolFactory = () @nogc => cast(Protocol) MmapPool.instance.make!P;
|
this.protocolFactory = () @nogc => cast(Protocol) defaultAllocator.make!P;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,7 +124,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = SList!int([5, 8, 15]);
|
auto l = SList!int([5, 8, 15]);
|
||||||
assert(l.front == 5);
|
assert(l.front == 5);
|
||||||
@ -172,19 +172,13 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = SList!int(2, 3);
|
auto l = SList!int(2, 3);
|
||||||
assert(l.length == 2);
|
assert(l.length == 2);
|
||||||
assert(l.front == 3);
|
assert(l.front == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l = SList!int(0, 0);
|
|
||||||
assert(l.empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
this(const size_t len, shared Allocator allocator = defaultAllocator)
|
this(const size_t len, shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
@ -192,7 +186,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = SList!int(2);
|
auto l = SList!int(2);
|
||||||
assert(l.length == 2);
|
assert(l.length == 2);
|
||||||
@ -263,7 +257,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 1, 234]);
|
auto l1 = SList!int([5, 1, 234]);
|
||||||
auto l2 = SList!int(l1);
|
auto l2 = SList!int(l1);
|
||||||
@ -289,7 +283,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 1, 234]);
|
auto l1 = SList!int([5, 1, 234]);
|
||||||
auto l2 = l1;
|
auto l2 = l1;
|
||||||
@ -308,7 +302,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l = SList!int([8, 5]);
|
SList!int l = SList!int([8, 5]);
|
||||||
|
|
||||||
@ -366,7 +360,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l;
|
SList!int l;
|
||||||
int value = 5;
|
int value = 5;
|
||||||
@ -419,7 +413,7 @@ struct SList(T)
|
|||||||
alias insert = insertFront;
|
alias insert = insertFront;
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l1;
|
SList!int l1;
|
||||||
|
|
||||||
@ -473,7 +467,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([234, 5, 1]);
|
auto l1 = SList!int([234, 5, 1]);
|
||||||
auto l2 = SList!int([5, 1]);
|
auto l2 = SList!int([5, 1]);
|
||||||
@ -502,7 +496,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 234, 30, 1]);
|
auto l1 = SList!int([5, 234, 30, 1]);
|
||||||
auto l2 = SList!int([5, 1]);
|
auto l2 = SList!int([5, 1]);
|
||||||
@ -526,7 +520,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([234, 5, 1]);
|
auto l1 = SList!int([234, 5, 1]);
|
||||||
auto l2 = SList!int([5, 1]);
|
auto l2 = SList!int([5, 1]);
|
||||||
@ -553,7 +547,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 234, 30, 1]);
|
auto l1 = SList!int([5, 234, 30, 1]);
|
||||||
auto l2 = SList!int([5, 1]);
|
auto l2 = SList!int([5, 1]);
|
||||||
@ -572,7 +566,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l;
|
SList!int l;
|
||||||
|
|
||||||
@ -600,7 +594,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l1, l2;
|
SList!int l1, l2;
|
||||||
|
|
||||||
@ -645,12 +639,12 @@ struct SList(T)
|
|||||||
{
|
{
|
||||||
auto n = this.head.next;
|
auto n = this.head.next;
|
||||||
|
|
||||||
this.allocator.dispose(this.head);
|
allocator.dispose(this.head);
|
||||||
this.head = n;
|
this.head = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l;
|
SList!int l;
|
||||||
|
|
||||||
@ -691,7 +685,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l = SList!int([8, 5, 4]);
|
SList!int l = SList!int([8, 5, 4]);
|
||||||
|
|
||||||
@ -726,7 +720,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 234, 30, 1]);
|
auto l1 = SList!int([5, 234, 30, 1]);
|
||||||
auto l2 = SList!int([5]);
|
auto l2 = SList!int([5]);
|
||||||
@ -784,7 +778,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 4, 9]);
|
auto l1 = SList!int([5, 4, 9]);
|
||||||
@ -834,7 +828,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 4, 9]);
|
auto l1 = SList!int([5, 4, 9]);
|
||||||
auto l2 = SList!int([9, 4]);
|
auto l2 = SList!int([9, 4]);
|
||||||
@ -842,14 +836,6 @@ struct SList(T)
|
|||||||
assert(l1 == l2);
|
assert(l1 == l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l1 = SList!int();
|
|
||||||
auto l2 = SList!int([9, 4]);
|
|
||||||
l1 = l2[];
|
|
||||||
assert(l1 == l2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a static array.
|
* Assigns a static array.
|
||||||
*
|
*
|
||||||
@ -865,7 +851,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = SList!int([5, 4, 9]);
|
auto l1 = SList!int([5, 4, 9]);
|
||||||
auto l2 = SList!int([9, 4]);
|
auto l2 = SList!int([9, 4]);
|
||||||
@ -877,7 +863,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l;
|
SList!int l;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -895,7 +881,7 @@ struct SList(T)
|
|||||||
assert(i == 3);
|
assert(i == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe @nogc private unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
interface Stuff
|
interface Stuff
|
||||||
{
|
{
|
||||||
@ -903,8 +889,14 @@ struct SList(T)
|
|||||||
static assert(is(SList!Stuff));
|
static assert(is(SList!Stuff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l = SList!int(0, 0);
|
||||||
|
assert(l.empty);
|
||||||
|
}
|
||||||
|
|
||||||
// foreach called using opIndex().
|
// foreach called using opIndex().
|
||||||
private @nogc @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
SList!int l;
|
SList!int l;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -921,6 +913,14 @@ private @nogc @safe unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l1 = SList!int();
|
||||||
|
auto l2 = SList!int([9, 4]);
|
||||||
|
l1 = l2[];
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward range for the $(D_PSYMBOL DList).
|
* Forward range for the $(D_PSYMBOL DList).
|
||||||
*
|
*
|
||||||
@ -1051,7 +1051,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = DList!int([5, 8, 15]);
|
auto l = DList!int([5, 8, 15]);
|
||||||
assert(l.front == 5);
|
assert(l.front == 5);
|
||||||
@ -1101,7 +1101,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = DList!int(2, 3);
|
auto l = DList!int(2, 3);
|
||||||
assert(l.length == 2);
|
assert(l.length == 2);
|
||||||
@ -1109,12 +1109,6 @@ struct DList(T)
|
|||||||
assert(l.back == 3);
|
assert(l.back == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l = DList!int(0, 0);
|
|
||||||
assert(l.empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
this(const size_t len, shared Allocator allocator = defaultAllocator)
|
this(const size_t len, shared Allocator allocator = defaultAllocator)
|
||||||
{
|
{
|
||||||
@ -1122,7 +1116,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = DList!int(2);
|
auto l = DList!int(2);
|
||||||
assert(l.length == 2);
|
assert(l.length == 2);
|
||||||
@ -1196,7 +1190,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 1, 234]);
|
auto l1 = DList!int([5, 1, 234]);
|
||||||
auto l2 = DList!int(l1);
|
auto l2 = DList!int(l1);
|
||||||
@ -1223,7 +1217,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 1, 234]);
|
auto l1 = DList!int([5, 1, 234]);
|
||||||
auto l2 = l1;
|
auto l2 = l1;
|
||||||
@ -1242,7 +1236,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l = DList!int([8, 5]);
|
DList!int l = DList!int([8, 5]);
|
||||||
|
|
||||||
@ -1278,7 +1272,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = DList!int([25]);
|
auto l = DList!int([25]);
|
||||||
assert(l.front == 25);
|
assert(l.front == 25);
|
||||||
@ -1371,7 +1365,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l;
|
DList!int l;
|
||||||
int value = 5;
|
int value = 5;
|
||||||
@ -1408,12 +1402,6 @@ struct DList(T)
|
|||||||
return inserted;
|
return inserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l1 = DList!int([5, 234]);
|
|
||||||
assert(l1.head is l1.head.next.prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
size_t insertFront(size_t R)(T[R] el)
|
size_t insertFront(size_t R)(T[R] el)
|
||||||
{
|
{
|
||||||
@ -1421,7 +1409,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l1;
|
DList!int l1;
|
||||||
|
|
||||||
@ -1497,7 +1485,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l;
|
DList!int l;
|
||||||
int value = 5;
|
int value = 5;
|
||||||
@ -1544,7 +1532,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l1;
|
DList!int l1;
|
||||||
|
|
||||||
@ -1601,7 +1589,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([234, 5, 1]);
|
auto l1 = DList!int([234, 5, 1]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1634,7 +1622,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([234, 5, 1]);
|
auto l1 = DList!int([234, 5, 1]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1665,7 +1653,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 234, 30, 1]);
|
auto l1 = DList!int([5, 234, 30, 1]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1716,7 +1704,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 234, 1]);
|
auto l1 = DList!int([5, 234, 1]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1726,15 +1714,6 @@ struct DList(T)
|
|||||||
assert(l1 == l2);
|
assert(l1 == l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
DList!int l;
|
|
||||||
l.insertAfter(l[], 234);
|
|
||||||
assert(l.front == 234);
|
|
||||||
assert(l.back == 234);
|
|
||||||
assert(l.length == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
size_t insertAfter(Range r, ref T el) @trusted
|
size_t insertAfter(Range r, ref T el) @trusted
|
||||||
in
|
in
|
||||||
@ -1760,7 +1739,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 1, 234]);
|
auto l1 = DList!int([5, 1, 234]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1790,7 +1769,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 234, 30, 1]);
|
auto l1 = DList!int([5, 234, 30, 1]);
|
||||||
auto l2 = DList!int([5, 1]);
|
auto l2 = DList!int([5, 1]);
|
||||||
@ -1827,7 +1806,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l;
|
DList!int l;
|
||||||
|
|
||||||
@ -1855,7 +1834,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l1, l2;
|
DList!int l1, l2;
|
||||||
|
|
||||||
@ -1900,7 +1879,7 @@ struct DList(T)
|
|||||||
{
|
{
|
||||||
auto n = this.head.next;
|
auto n = this.head.next;
|
||||||
|
|
||||||
allocator.dispose(this.head);
|
this.allocator_.dispose(this.head);
|
||||||
this.head = n;
|
this.head = n;
|
||||||
if (this.head is null)
|
if (this.head is null)
|
||||||
{
|
{
|
||||||
@ -1913,7 +1892,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l;
|
DList!int l;
|
||||||
|
|
||||||
@ -1949,7 +1928,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l = DList!int([9, 8]);
|
auto l = DList!int([9, 8]);
|
||||||
|
|
||||||
@ -1989,7 +1968,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l = DList!int([8, 5, 4]);
|
DList!int l = DList!int([8, 5, 4]);
|
||||||
|
|
||||||
@ -2016,7 +1995,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l = DList!int([8, 5, 4]);
|
DList!int l = DList!int([8, 5, 4]);
|
||||||
|
|
||||||
@ -2044,10 +2023,11 @@ struct DList(T)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Save references to the elements before and after the range.
|
// Save references to the elements before and after the range.
|
||||||
Entry* tailNext, headPrev;
|
Entry* headPrev;
|
||||||
if (*r.tail !is null && (*r.tail).next !is null)
|
Entry** tailNext;
|
||||||
|
if (*r.tail !is null)
|
||||||
{
|
{
|
||||||
tailNext = (*r.tail).next;
|
tailNext = &(*r.tail).next;
|
||||||
}
|
}
|
||||||
if (*r.head !is null)
|
if (*r.head !is null)
|
||||||
{
|
{
|
||||||
@ -2056,26 +2036,42 @@ struct DList(T)
|
|||||||
|
|
||||||
// Remove the elements.
|
// Remove the elements.
|
||||||
Entry* e = *r.head;
|
Entry* e = *r.head;
|
||||||
while (e !is tailNext)
|
while (e !is *tailNext)
|
||||||
{
|
{
|
||||||
auto next = e.next;
|
auto next = e.next;
|
||||||
allocator.dispose(e);
|
/* Workaround for dmd 2.076.1 bug on OSX. Invariants fail when
|
||||||
|
the allocator is called. Here it should be safe to use
|
||||||
|
allocator_ directory, since the list isn't empty.
|
||||||
|
See also removeFront. */
|
||||||
|
this.allocator_.dispose(e);
|
||||||
e = next;
|
e = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect the elements before and after the removed range.
|
// Connect the elements before and after the removed range.
|
||||||
if (tailNext !is null)
|
if (*tailNext !is null)
|
||||||
{
|
{
|
||||||
tailNext.prev = headPrev;
|
(*tailNext).prev = headPrev;
|
||||||
}
|
}
|
||||||
*r.head = tailNext;
|
else
|
||||||
*r.tail = tail;
|
{
|
||||||
|
this.tail = headPrev;
|
||||||
|
}
|
||||||
|
if (headPrev !is null)
|
||||||
|
{
|
||||||
|
headPrev.next = *tailNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.head = *tailNext;
|
||||||
|
}
|
||||||
|
r.head = tailNext;
|
||||||
|
r.tail = &this.tail;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 234, 30, 1]);
|
auto l1 = DList!int([5, 234, 30, 1]);
|
||||||
auto l2 = DList!int([5]);
|
auto l2 = DList!int([5]);
|
||||||
@ -2087,22 +2083,6 @@ struct DList(T)
|
|||||||
assert(l1 == l2);
|
assert(l1 == l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 260: https://issues.caraus.io/issues/260.
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l1 = DList!int([5, 234, 30, 1]);
|
|
||||||
auto l2 = DList!int([5, 1]);
|
|
||||||
auto r = l1[];
|
|
||||||
|
|
||||||
r.popFront();
|
|
||||||
r.popBack();
|
|
||||||
assert(r.front == 234);
|
|
||||||
assert(r.back == 30);
|
|
||||||
|
|
||||||
assert(!l1.remove(r).empty);
|
|
||||||
assert(l1 == l2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: Range that iterates over all elements of the container, in
|
* Returns: Range that iterates over all elements of the container, in
|
||||||
* forward order.
|
* forward order.
|
||||||
@ -2183,7 +2163,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 4, 9]);
|
auto l1 = DList!int([5, 4, 9]);
|
||||||
auto l2 = DList!int([9, 4]);
|
auto l2 = DList!int([9, 4]);
|
||||||
@ -2191,14 +2171,6 @@ struct DList(T)
|
|||||||
assert(l1 == l2);
|
assert(l1 == l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @safe @nogc unittest
|
|
||||||
{
|
|
||||||
auto l1 = DList!int();
|
|
||||||
auto l2 = DList!int([9, 4]);
|
|
||||||
l1 = l2[];
|
|
||||||
assert(l1 == l2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a static array.
|
* Assigns a static array.
|
||||||
*
|
*
|
||||||
@ -2214,7 +2186,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto l1 = DList!int([5, 4, 9]);
|
auto l1 = DList!int([5, 4, 9]);
|
||||||
auto l2 = DList!int([9, 4]);
|
auto l2 = DList!int([9, 4]);
|
||||||
@ -2226,7 +2198,7 @@ struct DList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
DList!int l;
|
DList!int l;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -2244,8 +2216,7 @@ struct DList(T)
|
|||||||
assert(i == 3);
|
assert(i == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 232: https://issues.caraus.io/issues/232.
|
@nogc nothrow pure @safe unittest
|
||||||
private @nogc unittest
|
|
||||||
{
|
{
|
||||||
class A
|
class A
|
||||||
{
|
{
|
||||||
@ -2253,3 +2224,67 @@ private @nogc unittest
|
|||||||
static assert(is(SList!(A*)));
|
static assert(is(SList!(A*)));
|
||||||
static assert(is(DList!(A*)));
|
static assert(is(DList!(A*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes all elements
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l = DList!int([5]);
|
||||||
|
assert(l.remove(l[]).empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l1 = DList!int([5, 234, 30, 1]);
|
||||||
|
auto l2 = DList!int([5, 1]);
|
||||||
|
auto r = l1[];
|
||||||
|
|
||||||
|
r.popFront();
|
||||||
|
r.popBack();
|
||||||
|
assert(r.front == 234);
|
||||||
|
assert(r.back == 30);
|
||||||
|
|
||||||
|
assert(!l1.remove(r).empty);
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l = DList!int(0, 0);
|
||||||
|
assert(l.empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l1 = DList!int([5, 234]);
|
||||||
|
assert(l1.head is l1.head.next.prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
DList!int l;
|
||||||
|
l.insertAfter(l[], 234);
|
||||||
|
assert(l.front == 234);
|
||||||
|
assert(l.back == 234);
|
||||||
|
assert(l.length == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l1 = DList!int();
|
||||||
|
auto l2 = DList!int([9, 4]);
|
||||||
|
l1 = l2[];
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the new head
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto l1 = DList!int([5, 234, 30, 1]);
|
||||||
|
auto l2 = DList!int([1]);
|
||||||
|
auto r = l1[];
|
||||||
|
|
||||||
|
r.popBack();
|
||||||
|
|
||||||
|
assert(!l1.remove(r).empty);
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
@ -1564,10 +1564,12 @@ struct String
|
|||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto oldLen = this.data + length;
|
const oldLength = length;
|
||||||
|
const rangeEnd = r.end - this.data;
|
||||||
const inserted = insertBack(el);
|
const inserted = insertBack(el);
|
||||||
bringToFront(ByCodeUnit!char(this, r.end, oldLen),
|
auto containerEnd = this.data + oldLength;
|
||||||
ByCodeUnit!char(this, oldLen, this.data + length));
|
bringToFront(ByCodeUnit!char(this, this.data + rangeEnd, containerEnd),
|
||||||
|
ByCodeUnit!char(this, containerEnd, this.data + length));
|
||||||
return inserted;
|
return inserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,15 +30,15 @@ else
|
|||||||
* Calculates the absolute value of a number.
|
* Calculates the absolute value of a number.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* I = Value type.
|
* T = Argument type.
|
||||||
* x = Value.
|
* x = Argument.
|
||||||
*
|
*
|
||||||
* Returns: Absolute value of $(D_PARAM x).
|
* Returns: Absolute value of $(D_PARAM x).
|
||||||
*/
|
*/
|
||||||
I abs(I)(I x)
|
T abs(T)(T x)
|
||||||
if (isIntegral!I)
|
if (isIntegral!T)
|
||||||
{
|
{
|
||||||
static if (isSigned!I)
|
static if (isSigned!T)
|
||||||
{
|
{
|
||||||
return x >= 0 ? x : -x;
|
return x >= 0 ? x : -x;
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ if (isIntegral!I)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
int i = -1;
|
int i = -1;
|
||||||
assert(i.abs == 1);
|
assert(i.abs == 1);
|
||||||
@ -63,25 +63,25 @@ pure nothrow @safe @nogc unittest
|
|||||||
version (D_Ddoc)
|
version (D_Ddoc)
|
||||||
{
|
{
|
||||||
/// ditto
|
/// ditto
|
||||||
I abs(I)(I x)
|
T abs(T)(T x)
|
||||||
if (isFloatingPoint!I);
|
if (isFloatingPoint!T);
|
||||||
}
|
}
|
||||||
else version (TanyaNative)
|
else version (TanyaNative)
|
||||||
{
|
{
|
||||||
extern I abs(I)(I number) pure nothrow @safe @nogc
|
extern T abs(T)(T number) @nogc nothrow pure @safe
|
||||||
if (isFloatingPoint!I);
|
if (isFloatingPoint!T);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
I abs(I)(I x)
|
T abs(T)(T x)
|
||||||
if (isFloatingPoint!I)
|
if (isFloatingPoint!T)
|
||||||
{
|
{
|
||||||
return fabs(cast(real) x);
|
return fabs(cast(real) x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
float f = -1.64;
|
float f = -1.64;
|
||||||
assert(f.abs == 1.64F);
|
assert(f.abs == 1.64F);
|
||||||
@ -97,7 +97,7 @@ pure nothrow @safe @nogc unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
I abs(I : Integer)(const auto ref I x)
|
T abs(T : Integer)(const auto ref T x)
|
||||||
{
|
{
|
||||||
auto result = Integer(x, x.allocator);
|
auto result = Integer(x, x.allocator);
|
||||||
result.sign = Sign.positive;
|
result.sign = Sign.positive;
|
||||||
@ -105,7 +105,7 @@ I abs(I : Integer)(const auto ref I x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
I abs(I : Integer)(I x)
|
T abs(T : Integer)(T x)
|
||||||
{
|
{
|
||||||
x.sign = Sign.positive;
|
x.sign = Sign.positive;
|
||||||
return x;
|
return x;
|
||||||
@ -117,37 +117,30 @@ version (D_Ddoc)
|
|||||||
* Calculates natural logarithm of $(D_PARAM x).
|
* Calculates natural logarithm of $(D_PARAM x).
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
|
* T = Argument type.
|
||||||
* x = Argument.
|
* x = Argument.
|
||||||
*
|
*
|
||||||
* Returns: Natural logarithm of $(D_PARAM x).
|
* Returns: Natural logarithm of $(D_PARAM x).
|
||||||
*/
|
*/
|
||||||
float ln(float x) pure nothrow @safe @nogc;
|
T ln(T)(T x)
|
||||||
/// ditto
|
if (isFloatingPoint!T);
|
||||||
double ln(double x) pure nothrow @safe @nogc;
|
|
||||||
/// ditto
|
|
||||||
real ln(real x) pure nothrow @safe @nogc;
|
|
||||||
}
|
}
|
||||||
else version (TanyaNative)
|
else version (TanyaNative)
|
||||||
{
|
{
|
||||||
extern float ln(float x) pure nothrow @safe @nogc;
|
extern T ln(T)(T x) @nogc nothrow pure @safe
|
||||||
extern double ln(double x) pure nothrow @safe @nogc;
|
if (isFloatingPoint!T);
|
||||||
extern real ln(real x) pure nothrow @safe @nogc;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float ln(float x) pure nothrow @safe @nogc
|
T ln(T)(T x)
|
||||||
|
if (isFloatingPoint!T)
|
||||||
{
|
{
|
||||||
return log(x);
|
return log(x);
|
||||||
}
|
}
|
||||||
double ln(double x) pure nothrow @safe @nogc
|
|
||||||
{
|
|
||||||
return log(x);
|
|
||||||
}
|
|
||||||
alias ln = log;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
import tanya.math;
|
import tanya.math;
|
||||||
|
|
||||||
|
@ -94,9 +94,31 @@ abstract class EntropySource
|
|||||||
Nullable!ubyte poll(out ubyte[maxGather] output) @nogc;
|
Nullable!ubyte poll(out ubyte[maxGather] output) @nogc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version (CRuntime_Bionic)
|
||||||
|
{
|
||||||
|
version = SecureARC4Random;
|
||||||
|
}
|
||||||
|
else version (OSX)
|
||||||
|
{
|
||||||
|
version = SecureARC4Random;
|
||||||
|
}
|
||||||
|
else version (OpenBSD)
|
||||||
|
{
|
||||||
|
version = SecureARC4Random;
|
||||||
|
}
|
||||||
|
else version (NetBSD)
|
||||||
|
{
|
||||||
|
version = SecureARC4Random;
|
||||||
|
}
|
||||||
|
else version (Solaris)
|
||||||
|
{
|
||||||
|
version = SecureARC4Random;
|
||||||
|
}
|
||||||
|
|
||||||
version (linux)
|
version (linux)
|
||||||
{
|
{
|
||||||
extern (C) long syscall(long number, ...) nothrow @system @nogc;
|
import core.stdc.config : c_long;
|
||||||
|
extern (C) c_long syscall(c_long number, ...) nothrow @system @nogc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses getrandom system call.
|
* Uses getrandom system call.
|
||||||
@ -137,7 +159,8 @@ version (linux)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
// int getrandom(void *buf, size_t buflen, unsigned int flags);
|
// int getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||||
auto length = syscall(318, output.ptr, output.length, 0);
|
import mir.linux._asm.unistd : NR_getrandom;
|
||||||
|
auto length = syscall(NR_getrandom, output.ptr, output.length, 0);
|
||||||
Nullable!ubyte ret;
|
Nullable!ubyte ret;
|
||||||
|
|
||||||
if (length >= 0)
|
if (length >= 0)
|
||||||
@ -148,16 +171,180 @@ version (linux)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version (X86_64)
|
@nogc @system unittest
|
||||||
{
|
{
|
||||||
private unittest
|
auto entropy = defaultAllocator.make!Entropy();
|
||||||
{
|
ubyte[blockSize] output;
|
||||||
auto entropy = defaultAllocator.make!Entropy();
|
output = entropy.random;
|
||||||
ubyte[blockSize] output;
|
|
||||||
output = entropy.random;
|
|
||||||
|
|
||||||
defaultAllocator.dispose(entropy);
|
defaultAllocator.dispose(entropy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else version (SecureARC4Random)
|
||||||
|
{
|
||||||
|
private extern (C) void arc4random_buf(scope void* buf, size_t nbytes) nothrow @nogc @system;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses arc4random_buf.
|
||||||
|
*/
|
||||||
|
class PlatformEntropySource : EntropySource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns: Minimum bytes required from the entropy source.
|
||||||
|
*/
|
||||||
|
override @property ubyte threshold() const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: Whether this entropy source is strong.
|
||||||
|
*/
|
||||||
|
override @property bool strong() const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll the entropy source.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* output = Buffer to save the generate random sequence (the method will
|
||||||
|
* to fill the buffer).
|
||||||
|
*
|
||||||
|
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||||
|
* or $(D_PSYMBOL Nullable!ubyte.init) on error.
|
||||||
|
*/
|
||||||
|
override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow @nogc @safe
|
||||||
|
{
|
||||||
|
(() @trusted => arc4random_buf(output.ptr, output.length))();
|
||||||
|
return Nullable!ubyte(cast(ubyte) (output.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc @system unittest
|
||||||
|
{
|
||||||
|
auto entropy = defaultAllocator.make!Entropy();
|
||||||
|
ubyte[blockSize] output;
|
||||||
|
output = entropy.random;
|
||||||
|
|
||||||
|
defaultAllocator.dispose(entropy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else version (Windows)
|
||||||
|
{
|
||||||
|
import core.sys.windows.basetsd : ULONG_PTR;
|
||||||
|
import core.sys.windows.windef : BOOL, DWORD, PBYTE;
|
||||||
|
import core.sys.windows.winnt : LPCSTR, LPCWSTR;
|
||||||
|
import core.sys.windows.wincrypt;
|
||||||
|
private extern(Windows) @nogc nothrow
|
||||||
|
{
|
||||||
|
BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE);
|
||||||
|
BOOL CryptAcquireContextA(HCRYPTPROV*, LPCSTR, LPCSTR, DWORD, DWORD);
|
||||||
|
BOOL CryptAcquireContextW(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
|
||||||
|
BOOL CryptReleaseContext(HCRYPTPROV, ULONG_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool initCryptGenRandom(scope ref HCRYPTPROV hProvider) @nogc nothrow @trusted
|
||||||
|
{
|
||||||
|
import core.sys.windows.winbase : GetLastError;
|
||||||
|
import core.sys.windows.winerror : NTE_BAD_KEYSET;
|
||||||
|
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx
|
||||||
|
// For performance reasons, we recommend that you set the pszContainer
|
||||||
|
// parameter to NULL and the dwFlags parameter to CRYPT_VERIFYCONTEXT
|
||||||
|
// in all situations where you do not require a persisted key.
|
||||||
|
// CRYPT_SILENT is intended for use with applications for which the UI cannot be displayed by the CSP.
|
||||||
|
if (!CryptAcquireContextW(&hProvider, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||||
|
{
|
||||||
|
if (GetLastError() == NTE_BAD_KEYSET)
|
||||||
|
{
|
||||||
|
// Attempt to create default container
|
||||||
|
if (!CryptAcquireContextA(&hProvider, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlatformEntropySource : EntropySource
|
||||||
|
{
|
||||||
|
private HCRYPTPROV hProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses CryptGenRandom.
|
||||||
|
*/
|
||||||
|
this() @nogc
|
||||||
|
{
|
||||||
|
if (!initCryptGenRandom(hProvider))
|
||||||
|
{
|
||||||
|
throw defaultAllocator.make!EntropyException("CryptAcquireContextW failed.");
|
||||||
|
}
|
||||||
|
assert(hProvider > 0, "hProvider not properly initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
~this() @nogc nothrow @safe
|
||||||
|
{
|
||||||
|
if (hProvider > 0)
|
||||||
|
{
|
||||||
|
(() @trusted => CryptReleaseContext(hProvider, 0))();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: Minimum bytes required from the entropy source.
|
||||||
|
*/
|
||||||
|
override @property ubyte threshold() const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: Whether this entropy source is strong.
|
||||||
|
*/
|
||||||
|
override @property bool strong() const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll the entropy source.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* output = Buffer to save the generate random sequence (the method will
|
||||||
|
* to fill the buffer).
|
||||||
|
*
|
||||||
|
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||||
|
* or $(D_PSYMBOL Nullable!ubyte.init) on error.
|
||||||
|
*/
|
||||||
|
override Nullable!ubyte poll(out ubyte[maxGather] output) @nogc nothrow @safe
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(hProvider > 0, "hProvider not properly initialized.");
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Nullable!ubyte ret;
|
||||||
|
if ((() @trusted => CryptGenRandom(hProvider, output.length, cast(PBYTE) output.ptr))())
|
||||||
|
{
|
||||||
|
ret = cast(ubyte) (output.length);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc @system unittest
|
||||||
|
{
|
||||||
|
auto entropy = defaultAllocator.make!Entropy();
|
||||||
|
ubyte[blockSize] output;
|
||||||
|
output = entropy.random;
|
||||||
|
|
||||||
|
defaultAllocator.dispose(entropy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,8 +367,6 @@ class Entropy
|
|||||||
|
|
||||||
private ubyte sourceCount_;
|
private ubyte sourceCount_;
|
||||||
|
|
||||||
private shared Allocator allocator;
|
|
||||||
|
|
||||||
/// Entropy accumulator.
|
/// Entropy accumulator.
|
||||||
protected SHA!(maxGather * 8, 512) accumulator;
|
protected SHA!(maxGather * 8, 512) accumulator;
|
||||||
|
|
||||||
@ -202,7 +387,7 @@ class Entropy
|
|||||||
{
|
{
|
||||||
allocator.resize(sources, maxSources);
|
allocator.resize(sources, maxSources);
|
||||||
|
|
||||||
version (linux)
|
static if (is(PlatformEntropySource))
|
||||||
{
|
{
|
||||||
this ~= allocator.make!PlatformEntropySource;
|
this ~= allocator.make!PlatformEntropySource;
|
||||||
}
|
}
|
||||||
@ -289,7 +474,7 @@ class Entropy
|
|||||||
|
|
||||||
if (!haveStrong)
|
if (!haveStrong)
|
||||||
{
|
{
|
||||||
throw allocator.make!EntropyException("No strong entropy source defined.");
|
throw defaultAllocator.make!EntropyException("No strong entropy source defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
output = accumulator.finish();
|
output = accumulator.finish();
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory.mallocator;
|
module tanya.memory.mallocator;
|
||||||
|
|
||||||
version (TanyaPhobos):
|
version (TanyaNative)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
|
||||||
import core.stdc.stdlib;
|
import core.stdc.stdlib;
|
||||||
import tanya.memory.allocator;
|
import tanya.memory.allocator;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Native allocator for Posix and Windows.
|
* Native allocator for Posix and Windows.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2017.
|
||||||
@ -82,7 +82,7 @@ else version (Windows)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This allocator allocates memory in regions (multiple of 64 KB for example).
|
* This allocator allocates memory in regions (multiple of 64 KB for example).
|
||||||
* Each region is then splitted in blocks. So it doesn't request the memory
|
* Each region is then splitted in blocks. So it doesn't request the memory
|
||||||
* from the operating system on each call, but only if there are no large
|
* from the operating system on each call, but only if there are no large
|
||||||
@ -106,6 +106,7 @@ else version (Windows)
|
|||||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use tanya.memory.mallocator instead")
|
||||||
final class MmapPool : Allocator
|
final class MmapPool : Allocator
|
||||||
{
|
{
|
||||||
version (none)
|
version (none)
|
||||||
@ -126,7 +127,7 @@ final class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Allocates $(D_PARAM size) bytes of memory.
|
* Allocates $(D_PARAM size) bytes of memory.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
@ -155,8 +156,7 @@ final class MmapPool : Allocator
|
|||||||
return data is null ? null : data[0 .. size];
|
return data is null ? null : data[0 .. size];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
nothrow unittest
|
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
assert(p);
|
assert(p);
|
||||||
@ -167,7 +167,7 @@ final class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Issue 245: https://issues.caraus.io/issues/245.
|
// Issue 245: https://issues.caraus.io/issues/245.
|
||||||
private @nogc unittest
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
{
|
{
|
||||||
// allocate() check.
|
// allocate() check.
|
||||||
size_t tooMuchMemory = size_t.max
|
size_t tooMuchMemory = size_t.max
|
||||||
@ -245,7 +245,7 @@ final class MmapPool : Allocator
|
|||||||
block.next = block.next.next;
|
block.next = block.next.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Deallocates a memory block.
|
* Deallocates a memory block.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
@ -299,15 +299,14 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
nothrow unittest
|
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
|
|
||||||
assert(MmapPool.instance.deallocate(p));
|
assert(MmapPool.instance.deallocate(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Reallocates a memory block in place if possible or returns
|
* Reallocates a memory block in place if possible or returns
|
||||||
* $(D_KEYWORD false). This function cannot be used to allocate or
|
* $(D_KEYWORD false). This function cannot be used to allocate or
|
||||||
* deallocate memory, so if $(D_PARAM p) is $(D_KEYWORD null) or
|
* deallocate memory, so if $(D_PARAM p) is $(D_KEYWORD null) or
|
||||||
@ -383,8 +382,7 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
nothrow unittest
|
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
assert(!MmapPool.instance.reallocateInPlace(p, 5));
|
assert(!MmapPool.instance.reallocateInPlace(p, 5));
|
||||||
@ -408,7 +406,7 @@ final class MmapPool : Allocator
|
|||||||
MmapPool.instance.deallocate(p);
|
MmapPool.instance.deallocate(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Increases or decreases the size of a memory block.
|
* Increases or decreases the size of a memory block.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
@ -449,8 +447,7 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
nothrow unittest
|
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
||||||
@ -514,7 +511,7 @@ final class MmapPool : Allocator
|
|||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Static allocator instance and initializer.
|
* Static allocator instance and initializer.
|
||||||
*
|
*
|
||||||
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
||||||
@ -524,8 +521,7 @@ final class MmapPool : Allocator
|
|||||||
return (cast(GetPureInstance!MmapPool) &instantiate)();
|
return (cast(GetPureInstance!MmapPool) &instantiate)();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
nothrow unittest
|
|
||||||
{
|
{
|
||||||
assert(instance is instance);
|
assert(instance is instance);
|
||||||
}
|
}
|
||||||
@ -622,7 +618,7 @@ final class MmapPool : Allocator
|
|||||||
/ pageSize * pageSize + pageSize;
|
/ pageSize * pageSize + pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns: Alignment offered.
|
* Returns: Alignment offered.
|
||||||
*/
|
*/
|
||||||
@property uint alignment() shared const pure nothrow @safe @nogc
|
@property uint alignment() shared const pure nothrow @safe @nogc
|
||||||
@ -630,7 +626,7 @@ final class MmapPool : Allocator
|
|||||||
return alignment_;
|
return alignment_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private nothrow @nogc unittest
|
version (TanyaNative) @nogc nothrow pure unittest
|
||||||
{
|
{
|
||||||
assert(MmapPool.instance.alignment == MmapPool.alignment_);
|
assert(MmapPool.instance.alignment == MmapPool.alignment_);
|
||||||
}
|
}
|
||||||
@ -661,9 +657,11 @@ final class MmapPool : Allocator
|
|||||||
private alias Block = shared BlockEntry*;
|
private alias Block = shared BlockEntry*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version (TanyaNative):
|
||||||
|
|
||||||
// A lot of allocations/deallocations, but it is the minimum caused a
|
// A lot of allocations/deallocations, but it is the minimum caused a
|
||||||
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
|
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
|
||||||
private @nogc unittest
|
@nogc nothrow pure unittest
|
||||||
{
|
{
|
||||||
auto a = MmapPool.instance.allocate(16);
|
auto a = MmapPool.instance.allocate(16);
|
||||||
auto d = MmapPool.instance.allocate(16);
|
auto d = MmapPool.instance.allocate(16);
|
||||||
|
@ -14,12 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory;
|
module tanya.memory;
|
||||||
|
|
||||||
import std.algorithm.iteration;
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import tanya.conv;
|
import tanya.conv;
|
||||||
import tanya.exception;
|
import tanya.exception;
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
import tanya.memory.mmappool;
|
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.range.primitive;
|
import tanya.range.primitive;
|
||||||
|
|
||||||
@ -94,13 +92,21 @@ private void _d_monitordelete(Object h, bool det) pure nothrow @nogc;
|
|||||||
|
|
||||||
shared Allocator allocator;
|
shared Allocator allocator;
|
||||||
|
|
||||||
shared static this() nothrow @nogc
|
|
||||||
{
|
|
||||||
allocator = MmapPool.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private shared(Allocator) getAllocatorInstance() nothrow @nogc
|
private shared(Allocator) getAllocatorInstance() nothrow @nogc
|
||||||
{
|
{
|
||||||
|
if (allocator is null)
|
||||||
|
{
|
||||||
|
version (TanyaNative)
|
||||||
|
{
|
||||||
|
import tanya.memory.mmappool;
|
||||||
|
defaultAllocator = MmapPool.instance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
import tanya.memory.mallocator;
|
||||||
|
defaultAllocator = Mallocator.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +250,7 @@ package(tanya) T[] resize(T)(shared Allocator allocator,
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
int[] p;
|
int[] p;
|
||||||
|
|
||||||
@ -267,6 +273,10 @@ private unittest
|
|||||||
*/
|
*/
|
||||||
package(tanya) void[] finalize(T)(ref T* p)
|
package(tanya) void[] finalize(T)(ref T* p)
|
||||||
{
|
{
|
||||||
|
if (p is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
static if (hasElaborateDestructor!T)
|
static if (hasElaborateDestructor!T)
|
||||||
{
|
{
|
||||||
destroy(*p);
|
destroy(*p);
|
||||||
@ -333,7 +343,10 @@ package(tanya) void[] finalize(T)(ref T[] p)
|
|||||||
{
|
{
|
||||||
static if (hasElaborateDestructor!(typeof(p[0])))
|
static if (hasElaborateDestructor!(typeof(p[0])))
|
||||||
{
|
{
|
||||||
p.each!((ref e) => destroy(e));
|
foreach (ref e; p)
|
||||||
|
{
|
||||||
|
destroy(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -354,11 +367,11 @@ void dispose(T)(shared Allocator allocator, auto ref T p)
|
|||||||
p = null;
|
p = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
~this()
|
~this() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,7 +381,7 @@ private unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Works with interfaces.
|
// Works with interfaces.
|
||||||
private pure unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
interface I
|
interface I
|
||||||
{
|
{
|
||||||
@ -457,7 +470,7 @@ do
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
int* i = defaultAllocator.make!int(5);
|
int* i = defaultAllocator.make!int(5);
|
||||||
assert(*i == 5);
|
assert(*i == 5);
|
||||||
@ -492,7 +505,7 @@ do
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
int[] i = defaultAllocator.make!(int[])(2);
|
int[] i = defaultAllocator.make!(int[])(2);
|
||||||
assert(i.length == 2);
|
assert(i.length == 2);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* This module provides a portable way of using operating system error codes.
|
* This module provides a portable way of using operating system error codes.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.os.error;
|
module tanya.os.error;
|
||||||
|
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
// Socket API error.
|
// Socket API error.
|
||||||
private template SAError(int posix, int wsa = posix)
|
private template SAError(int posix, int wsa = posix)
|
||||||
{
|
{
|
||||||
@ -120,7 +122,7 @@ struct ErrorCode
|
|||||||
/// Protocol not available.
|
/// Protocol not available.
|
||||||
noProtocolOption = SAError!(92, 42),
|
noProtocolOption = SAError!(92, 42),
|
||||||
|
|
||||||
/// The protocol is not implemented orR has not been configured.
|
/// The protocol is not implemented or has not been configured.
|
||||||
protocolNotSupported = SAError!(93, 43),
|
protocolNotSupported = SAError!(93, 43),
|
||||||
|
|
||||||
/// The support for the specified socket type does not exist in this
|
/// The support for the specified socket type does not exist in this
|
||||||
@ -186,19 +188,66 @@ struct ErrorCode
|
|||||||
cancelled = SAError!(125, 103),
|
cancelled = SAError!(125, 103),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error descriptions.
|
||||||
|
*/
|
||||||
|
private enum ErrorStr : string
|
||||||
|
{
|
||||||
|
success = "The operation completed successfully",
|
||||||
|
noPermission = "Operation not permitted",
|
||||||
|
interrupted = "Interrupted system call",
|
||||||
|
badDescriptor = "Bad file descriptor",
|
||||||
|
wouldBlock = "An operation on a non-blocking socket would block",
|
||||||
|
noMemory = "Out of memory",
|
||||||
|
accessDenied = "Access denied",
|
||||||
|
fault = "An invalid pointer address detected",
|
||||||
|
noSuchDevice = "No such device",
|
||||||
|
invalidArgument = "An invalid argument was supplied",
|
||||||
|
tooManyDescriptors = "The limit on the number of open file descriptors",
|
||||||
|
noDescriptors = "The limit on the number of open file descriptors",
|
||||||
|
brokenPipe = "Broken pipe",
|
||||||
|
nameTooLong = "The name was too long",
|
||||||
|
notSocket = "A socket operation was attempted on a non-socket",
|
||||||
|
protocolError = "Protocol error",
|
||||||
|
messageTooLong = "Message too long",
|
||||||
|
wrongProtocolType = "Wrong protocol type for socket",
|
||||||
|
noProtocolOption = "Protocol not available",
|
||||||
|
protocolNotSupported = "The protocol is not implemented or has not been configured",
|
||||||
|
socketNotSupported = "Socket type not supported",
|
||||||
|
operationNotSupported = "The address family is no supported by the protocol family",
|
||||||
|
addressFamilyNotSupported = "Address family specified is not supported",
|
||||||
|
addressInUse = "Address already in use",
|
||||||
|
networkDown = "The network is not available",
|
||||||
|
networkUnreachable = "No route to host",
|
||||||
|
networkReset = "Network dropped connection because of reset",
|
||||||
|
connectionAborted = "The connection has been aborted",
|
||||||
|
connectionReset = "Connection reset by peer",
|
||||||
|
noBufferSpace = "No free buffer space is available for a socket operation",
|
||||||
|
alreadyConnected = "Transport endpoint is already connected",
|
||||||
|
notConnected = "Transport endpoint is not connected",
|
||||||
|
shutdown = "Cannot send after transport endpoint shutdown",
|
||||||
|
timedOut = "Operation timed out",
|
||||||
|
connectionRefused = "Connection refused",
|
||||||
|
hostDown = "Host is down",
|
||||||
|
hostUnreachable = "No route to host",
|
||||||
|
alreadyStarted = "Operation already in progress",
|
||||||
|
inProgress = "Operation now in progress",
|
||||||
|
cancelled = "Operation cancelled",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* value = Numeric error code.
|
* value = Numeric error code.
|
||||||
*/
|
*/
|
||||||
this(const ErrorNo value) pure nothrow @safe @nogc
|
this(const ErrorNo value) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
this.value_ = value;
|
this.value_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
ErrorCode ec;
|
ErrorCode ec;
|
||||||
assert(ec == ErrorCode.success);
|
assert(ec == ErrorCode.success);
|
||||||
@ -211,13 +260,13 @@ struct ErrorCode
|
|||||||
* Resets this $(D_PSYMBOL ErrorCode) to default
|
* Resets this $(D_PSYMBOL ErrorCode) to default
|
||||||
* ($(D_PSYMBOL ErrorCode.success)).
|
* ($(D_PSYMBOL ErrorCode.success)).
|
||||||
*/
|
*/
|
||||||
void reset() pure nothrow @safe @nogc
|
void reset() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
this.value_ = ErrorNo.success;
|
this.value_ = ErrorNo.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto ec = ErrorCode(ErrorCode.fault);
|
auto ec = ErrorCode(ErrorCode.fault);
|
||||||
assert(ec == ErrorCode.fault);
|
assert(ec == ErrorCode.fault);
|
||||||
@ -241,7 +290,7 @@ struct ErrorCode
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
ErrorCode ec = ErrorCode.fault;
|
ErrorCode ec = ErrorCode.fault;
|
||||||
auto errorNo = cast(ErrorCode.ErrorNo) ec;
|
auto errorNo = cast(ErrorCode.ErrorNo) ec;
|
||||||
@ -258,38 +307,38 @@ struct ErrorCode
|
|||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD this).
|
* Returns: $(D_KEYWORD this).
|
||||||
*/
|
*/
|
||||||
ref ErrorCode opAssign(const ErrorNo that) pure nothrow @safe @nogc
|
ref ErrorCode opAssign(const ErrorNo that) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
this.value_ = that;
|
this.value_ = that;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ref ErrorCode opAssign()(auto ref const ErrorCode that)
|
ref ErrorCode opAssign(const ErrorCode that) @nogc nothrow pure @safe
|
||||||
pure nothrow @safe @nogc
|
|
||||||
{
|
{
|
||||||
this.value_ = that.value_;
|
this.value_ = that.value_;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
{
|
ErrorCode ec;
|
||||||
ErrorCode ec;
|
assert(ec == ErrorCode.success);
|
||||||
assert(ec == ErrorCode.success);
|
|
||||||
|
|
||||||
ec = ErrorCode.fault;
|
ec = ErrorCode.fault;
|
||||||
assert(ec == ErrorCode.fault);
|
assert(ec == ErrorCode.fault);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
auto ec1 = ErrorCode(ErrorCode.fault);
|
|
||||||
ErrorCode ec2;
|
|
||||||
assert(ec2 == ErrorCode.success);
|
|
||||||
|
|
||||||
ec2 = ec1;
|
///
|
||||||
assert(ec1 == ec2);
|
@nogc nothrow pure @safe unittest
|
||||||
}
|
{
|
||||||
|
auto ec1 = ErrorCode(ErrorCode.fault);
|
||||||
|
ErrorCode ec2;
|
||||||
|
assert(ec2 == ErrorCode.success);
|
||||||
|
|
||||||
|
ec2 = ec1;
|
||||||
|
assert(ec1 == ec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -300,37 +349,68 @@ struct ErrorCode
|
|||||||
*
|
*
|
||||||
* Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal.
|
* Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal.
|
||||||
*/
|
*/
|
||||||
bool opEquals(const ErrorNo that) const pure nothrow @safe @nogc
|
bool opEquals(const ErrorNo that) const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this.value_ == that;
|
return this.value_ == that;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
bool opEquals()(auto ref const ErrorCode that)
|
bool opEquals(const ErrorCode that) const @nogc nothrow pure @safe
|
||||||
const pure nothrow @safe @nogc
|
|
||||||
{
|
{
|
||||||
return this.value_ == that.value_;
|
return this.value_ == that.value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
{
|
ErrorCode ec1 = ErrorCode.fault;
|
||||||
ErrorCode ec1 = ErrorCode.fault;
|
ErrorCode ec2 = ErrorCode.accessDenied;
|
||||||
ErrorCode ec2 = ErrorCode.accessDenied;
|
|
||||||
|
|
||||||
assert(ec1 != ec2);
|
assert(ec1 != ec2);
|
||||||
assert(ec1 != ErrorCode.accessDenied);
|
assert(ec1 != ErrorCode.accessDenied);
|
||||||
assert(ErrorCode.fault != ec2);
|
assert(ErrorCode.fault != ec2);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
ErrorCode ec1 = ErrorCode.fault;
|
|
||||||
ErrorCode ec2 = ErrorCode.fault;
|
|
||||||
|
|
||||||
assert(ec1 == ec2);
|
///
|
||||||
assert(ec1 == ErrorCode.fault);
|
@nogc nothrow pure @safe unittest
|
||||||
assert(ErrorCode.fault == ec2);
|
{
|
||||||
|
ErrorCode ec1 = ErrorCode.fault;
|
||||||
|
ErrorCode ec2 = ErrorCode.fault;
|
||||||
|
|
||||||
|
assert(ec1 == ec2);
|
||||||
|
assert(ec1 == ErrorCode.fault);
|
||||||
|
assert(ErrorCode.fault == ec2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns string describing the error number. If a description for a
|
||||||
|
* specific error number is not available, returns $(D_KEYWORD null).
|
||||||
|
*
|
||||||
|
* Returns: String describing the error number.
|
||||||
|
*/
|
||||||
|
string toString() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
foreach (e; __traits(allMembers, ErrorNo))
|
||||||
|
{
|
||||||
|
if (__traits(getMember, ErrorNo, e) == this.value_)
|
||||||
|
{
|
||||||
|
return __traits(getMember, ErrorStr, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ErrorCode ec = ErrorCode.fault;
|
||||||
|
assert(ec.toString() == "An invalid pointer address detected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ErrorCode ec = cast(ErrorCode.ErrorNo) -1;
|
||||||
|
assert(ec.toString() is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ErrorNo value_ = ErrorNo.success;
|
private ErrorNo value_ = ErrorNo.success;
|
||||||
|
@ -633,8 +633,8 @@ template isBidirectionalRange(R)
|
|||||||
*
|
*
|
||||||
* A random-access range is a range that allows random access to its
|
* A random-access range is a range that allows random access to its
|
||||||
* elements by index using $(D_INLINECODE [])-operator (defined with
|
* elements by index using $(D_INLINECODE [])-operator (defined with
|
||||||
* $(D_INLINECODE opIndex())). Further a random access range should be a
|
* $(D_INLINECODE opIndex())). Further a random access range should
|
||||||
* bidirectional range that also has a length or an infinite forward range.
|
* have a length or be infinite.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* R = The type to be tested.
|
* R = The type to be tested.
|
||||||
@ -642,19 +642,21 @@ template isBidirectionalRange(R)
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM R) is a random-access range,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM R) is a random-access range,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*
|
*
|
||||||
* See_Also: $(D_PSYMBOL isBidirectionalRange),
|
* See_Also: $(D_PSYMBOL isInfinite),
|
||||||
* $(D_PSYMBOL isForwardRange),
|
|
||||||
* $(D_PSYMBOL isInfinite),
|
|
||||||
* $(D_PSYMBOL hasLength).
|
* $(D_PSYMBOL hasLength).
|
||||||
|
*
|
||||||
|
* Note: This definition differs from `std.range.primitives.isRandomAccessRange`
|
||||||
|
* in the D standard library in that it does not also require $(D_PARAM R) to
|
||||||
|
* be a forward range and a bidirectional range. Those properties may be tested
|
||||||
|
* separately with $(D_PSYMBOL isForwardRange) and
|
||||||
|
* $(D_PSYMBOL isBidirectionalRange).
|
||||||
*/
|
*/
|
||||||
template isRandomAccessRange(R)
|
template isRandomAccessRange(R)
|
||||||
{
|
{
|
||||||
static if (is(ReturnType!((R r) => r.opIndex(size_t.init)) U))
|
static if (is(ReturnType!((R r) => r.opIndex(size_t.init)) U))
|
||||||
{
|
{
|
||||||
private enum bool isBidirectional = isBidirectionalRange!R
|
enum bool isRandomAccessRange = isInputRange!R
|
||||||
&& hasLength!R;
|
&& (hasLength!R || isInfinite!R)
|
||||||
private enum bool isForward = isInfinite!R && isForwardRange!R;
|
|
||||||
enum bool isRandomAccessRange = (isBidirectional || isForward)
|
|
||||||
&& is(U == ReturnType!((R r) => r.front()));
|
&& is(U == ReturnType!((R r) => r.front()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -92,7 +92,7 @@ template Pair(Specs...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static assert(is(Pair!(int, int)));
|
static assert(is(Pair!(int, int)));
|
||||||
static assert(!is(Pair!(int, 5)));
|
static assert(!is(Pair!(int, 5)));
|
||||||
|
Reference in New Issue
Block a user