Improve InterfaceProxy(Class).
- InterfaceProxyClass can now be allocated/freed using a custom allocator - Non-copyable values can be moved into an InterfaceProxyClass instance - Non-copyable values can be moved into an InterfaceProxy
This commit is contained in:
parent
b68d23f515
commit
c95306245f
|
@ -1,6 +1,9 @@
|
||||||
module vibe.internal.interfaceproxy;
|
module vibe.internal.interfaceproxy;
|
||||||
|
|
||||||
import vibe.internal.traits;
|
import vibe.internal.traits;
|
||||||
|
import vibe.internal.freelistref;
|
||||||
|
import vibe.internal.allocator;
|
||||||
|
import std.algorithm.mutation : move, swap;
|
||||||
import std.meta : staticMap;
|
import std.meta : staticMap;
|
||||||
import std.traits : BaseTypeTuple;
|
import std.traits : BaseTypeTuple;
|
||||||
|
|
||||||
|
@ -8,6 +11,20 @@ import std.traits : BaseTypeTuple;
|
||||||
O asInterface(I, O)(O obj) if (is(I == interface) && is(O : I)) { return obj; }
|
O asInterface(I, O)(O obj) if (is(I == interface) && is(O : I)) { return obj; }
|
||||||
InterfaceProxyClass!(I, O) asInterface(I, O)(O obj) if (is(I == interface) && !is(O : I)) { return new InterfaceProxyClass!(I, O)(obj); }
|
InterfaceProxyClass!(I, O) asInterface(I, O)(O obj) if (is(I == interface) && !is(O : I)) { return new InterfaceProxyClass!(I, O)(obj); }
|
||||||
|
|
||||||
|
InterfaceProxyClass!(I, O) asInterface(I, O)(O obj, IAllocator allocator)
|
||||||
|
@trusted if (is(I == interface) && !is(O : I))
|
||||||
|
{
|
||||||
|
alias R = InterfaceProxyClass!(I, O);
|
||||||
|
return allocator.makeGCSafe!R(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeInterface(I, O)(InterfaceProxyClass!(I, O) inst, IAllocator allocator)
|
||||||
|
{
|
||||||
|
allocator.disposeGCSafe(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeListRef!(InterfaceProxyClass!(I, O)) asInterfaceFL(I, O)(O obj) { return FreeListRef!(InterfaceProxyClass!(I, O))(obj); }
|
||||||
|
|
||||||
InterfaceProxy!I interfaceProxy(I, O)(O o) { return InterfaceProxy!I(o); }
|
InterfaceProxy!I interfaceProxy(I, O)(O o) { return InterfaceProxy!I(o); }
|
||||||
|
|
||||||
private final class InterfaceProxyClass(I, O) : I
|
private final class InterfaceProxyClass(I, O) : I
|
||||||
|
@ -19,7 +36,7 @@ private final class InterfaceProxyClass(I, O) : I
|
||||||
O m_obj;
|
O m_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(O obj) { m_obj = obj; }
|
this(ref O obj) { swap(m_obj, obj); }
|
||||||
|
|
||||||
mixin methodDefs!0;
|
mixin methodDefs!0;
|
||||||
|
|
||||||
|
@ -65,25 +82,28 @@ struct InterfaceProxy(I) if (is(I == interface)) {
|
||||||
import vibe.internal.traits : checkInterfaceConformance;
|
import vibe.internal.traits : checkInterfaceConformance;
|
||||||
|
|
||||||
private {
|
private {
|
||||||
void[4*(void*).sizeof] m_value;
|
void*[4] m_value;
|
||||||
|
enum maxSize = m_value.length * m_value[0].sizeof;
|
||||||
Proxy m_intf;
|
Proxy m_intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(IP : InterfaceProxy!J, J)(IP proxy) @safe
|
this(IP : InterfaceProxy!J, J)(IP proxy) @safe
|
||||||
{
|
{
|
||||||
() @trusted { m_value[] = proxy.m_value[]; } ();
|
() @trusted {
|
||||||
m_intf = proxy.m_intf;
|
swap(proxy.m_value, m_value);
|
||||||
m_intf._postblit(m_value);
|
proxy.m_intf = null;
|
||||||
|
} ();
|
||||||
}
|
}
|
||||||
|
|
||||||
this(O)(O object) @trusted
|
this(O)(O object) @trusted
|
||||||
{
|
{
|
||||||
static assert(O.sizeof <= m_value.length, "Object ("~O.stringof~") is too big to be stored in an InterfaceProxy.");
|
static assert(O.sizeof % m_value[0].sizeof == 0, "Sizeof object ("~O.stringof~") must be a multiple of a pointer size.");
|
||||||
|
static assert(O.sizeof <= maxSize, "Object ("~O.stringof~") is too big to be stored in an InterfaceProxy.");
|
||||||
import std.conv : emplace;
|
import std.conv : emplace;
|
||||||
m_intf = ProxyImpl!O.get();
|
m_intf = ProxyImpl!O.get();
|
||||||
static if (is(O == struct))
|
static if (is(O == struct))
|
||||||
emplace!O(m_value[0 .. O.sizeof]);
|
emplace!O(m_value[0 .. O.sizeof/m_value[0].sizeof]);
|
||||||
(cast(O[])m_value[0 .. O.sizeof])[0] = object;
|
swap((cast(O[])m_value[0 .. O.sizeof/m_value[0].sizeof])[0], object);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() @safe
|
~this() @safe
|
||||||
|
@ -101,7 +121,7 @@ struct InterfaceProxy(I) if (is(I == interface)) {
|
||||||
if (m_intf) {
|
if (m_intf) {
|
||||||
m_intf._destroy(m_value);
|
m_intf._destroy(m_value);
|
||||||
m_intf = null;
|
m_intf = null;
|
||||||
() @trusted { (cast(ubyte[])m_value)[] = 0; } ();
|
m_value[] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +129,7 @@ struct InterfaceProxy(I) if (is(I == interface)) {
|
||||||
@trusted nothrow {
|
@trusted nothrow {
|
||||||
if (!m_intf || m_intf._typeInfo() !is typeid(T))
|
if (!m_intf || m_intf._typeInfo() !is typeid(T))
|
||||||
assert(false, "Extraction of wrong type from InterfaceProxy.");
|
assert(false, "Extraction of wrong type from InterfaceProxy.");
|
||||||
return (cast(T[])m_value[0 .. T.sizeof])[0];
|
return (cast(T[])m_value[0 .. T.sizeof/m_value[0].sizeof])[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void opAssign(IP : InterfaceProxy!J, J)(IP proxy) @safe
|
void opAssign(IP : InterfaceProxy!J, J)(IP proxy) @safe
|
||||||
|
@ -118,23 +138,24 @@ struct InterfaceProxy(I) if (is(I == interface)) {
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
if (proxy.m_intf) {
|
if (proxy.m_intf) {
|
||||||
() @trusted { m_value[] = proxy.m_value[]; } ();
|
|
||||||
m_intf = proxy.m_intf;
|
m_intf = proxy.m_intf;
|
||||||
m_intf._postblit(m_value);
|
m_value[] = proxy.m_value[];
|
||||||
|
proxy.m_intf = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void opAssign(O)(O object) @trusted
|
void opAssign(O)(O object) @trusted
|
||||||
if (checkInterfaceConformance!(O, I) is null)
|
if (checkInterfaceConformance!(O, I) is null)
|
||||||
{
|
{
|
||||||
static assert(O.sizeof <= m_value.length, "Object is too big to be stored in an InterfaceProxy.");
|
static assert(O.sizeof % m_value[0].sizeof == 0, "Sizeof object ("~O.stringof~") must be a multiple of a pointer size.");
|
||||||
|
static assert(O.sizeof <= maxSize, "Object is too big to be stored in an InterfaceProxy.");
|
||||||
import std.conv : emplace;
|
import std.conv : emplace;
|
||||||
clear();
|
clear();
|
||||||
m_intf = ProxyImpl!O.get();
|
m_intf = ProxyImpl!O.get();
|
||||||
if (is(O == class))
|
if (is(O == class))
|
||||||
(cast(O[])m_value[0 .. O.sizeof])[0] = object;
|
(cast(O[])m_value[0 .. O.sizeof/m_value[0].sizeof])[0] = object;
|
||||||
else emplace!O(m_value[0 .. O.sizeof]);
|
else emplace!O(m_value[0 .. O.sizeof/m_value[0].sizeof]);
|
||||||
(cast(O[])m_value[0 .. O.sizeof])[0] = object;
|
swap((cast(O[])m_value[0 .. O.sizeof/m_value[0].sizeof])[0], object);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opCast(T)() const @safe nothrow if (is(T == bool)) { return m_intf !is null; }
|
bool opCast(T)() const @safe nothrow if (is(T == bool)) { return m_intf !is null; }
|
||||||
|
|
Loading…
Reference in a new issue