digitalmars.D.learn - Need help to compile code with traits
- Xavier Bigand (7/63) Feb 05 2017 Hi,
- Basile B. (47/133) Feb 05 2017 The whole thing you do to initialize could be replaced by a copy
- Xavier Bigand (4/139) Feb 05 2017 Certainly I didn't think a lot about it for the moment.
Hi, I am trying to create an allocator that don't use the GC, and I have issues for the initialization of member before calling the constructor. Here is my actual code :mixin template NogcAllocator(T) { static T nogcNew(T, Args...)(Args args) nogc { import core.stdc.stdlib : malloc; import std.traits; T instance; instance = cast(T)malloc(__traits(classInstanceSize, T)); foreach (string member; __traits(allMembers, T)) { static if (isType!(__traits(getMember, T, member))) __traits(getMember, instance, member) = typeof(__traits(getMember, T, member)).init; } instance.__ctor(args); return instance; } static void nogcDelete(T)(T instance) nogc { import core.stdc.stdlib : free; instance.__dtor(); free(instance); } } unittest { struct Dummy { int field1 = 10; int field2 = 11; } class MyClass { mixin NogcAllocator!MyClass; int a = 0; int[] b = [1, 2, 3]; Dummy c = Dummy(4, 5); int d = 6; this() nogc { } this(int val) nogc { d = val; } } MyClass first = MyClass.nogcNew!MyClass(); MyClass second = MyClass.nogcNew!MyClass(7); assert(first.a == 0); assert(first.b == [1, 2, 3]); assert(first.c.field1 == 4); assert(first.d == 6); assert(second.c.field1 == 4); assert(second.d == 7); }And the compilation errors :..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(63): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClas ).nogcNew!(MyClass) error instantiating ..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(64): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClas ).nogcNew!(MyClass, int) error instantiatingI don't understand my mistake with the getMember and isType traits. And I am curious about of what is the Monitor.
Feb 05 2017
On Sunday, 5 February 2017 at 14:59:04 UTC, Xavier Bigand wrote:Hi, I am trying to create an allocator that don't use the GC, and I have issues for the initialization of member before calling the constructor. Here is my actual code :The whole thing you do to initialize could be replaced by a copy of the initializer, which is what emplace does: static T nogcNew(T, Args...)(Args args) nogc { import core.stdc.stdlib : malloc; import std.traits, std.meta; T instance; enum s = __traits(classInstanceSize, T); instance = cast(T) malloc(s); (cast(void*) instance)[0..s] = typeid(T).initializer[]; instance.__ctor(args); return instance; } Your nogcDelete() is bug-prone & leaky - use _xdtor, which also calls the __dtor injected by mixin. - even if you do so, __xdtors are not inherited !! instead dtor in parent classes are called by destroy() directly. Currently what I do to simulate inherited destructor is to mix this for each new generation. mixin template inheritedDtor() { private: import std.traits: BaseClassesTuple; alias B = BaseClassesTuple!(typeof(this)); enum hasDtor = __traits(hasMember, typeof(this), "__dtor"); static if (hasDtor && !__traits(isSame, __traits(parent, typeof(this).__dtor), typeof(this))) enum inDtor = true; else enum inDtor = false; public void callInheritedDtor(classT = typeof(this))() { import std.meta: aliasSeqOf; import std.range: iota; foreach(i; aliasSeqOf!(iota(0, B.length))) static if (__traits(hasMember, B[i], "__xdtor")) { mixin("this." ~ B[i].stringof ~ ".__xdtor;"); break; } } static if (!hasDtor || inDtor) public ~this() {callInheritedDtor();} } When a dtor is implemented it has to call "callInheritedDtor()" at end of the dtor implementation.mixin template NogcAllocator(T) { static T nogcNew(T, Args...)(Args args) nogc { import core.stdc.stdlib : malloc; import std.traits; T instance; instance = cast(T)malloc(__traits(classInstanceSize, T)); foreach (string member; __traits(allMembers, T)) { static if (isType!(__traits(getMember, T, member))) __traits(getMember, instance, member) = typeof(__traits(getMember, T, member)).init; } instance.__ctor(args); return instance; } static void nogcDelete(T)(T instance) nogc { import core.stdc.stdlib : free; instance.__dtor(); free(instance); } } unittest { struct Dummy { int field1 = 10; int field2 = 11; } class MyClass { mixin NogcAllocator!MyClass; int a = 0; int[] b = [1, 2, 3]; Dummy c = Dummy(4, 5); int d = 6; this() nogc { } this(int val) nogc { d = val; } } MyClass first = MyClass.nogcNew!MyClass(); MyClass second = MyClass.nogcNew!MyClass(7); assert(first.a == 0); assert(first.b == [1, 2, 3]); assert(first.c.field1 == 4); assert(first.d == 6); assert(second.c.field1 == 4); assert(second.d == 7); }And the compilation errors :..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(63): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClas ).nogcNew!(MyClass) error instantiating ..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(64): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClas ).nogcNew!(MyClass, int) error instantiatingI don't understand my mistake with the getMember and isType traits. And I am curious about of what is the Monitor.
Feb 05 2017
Le 05/02/2017 à 18:32, Basile B. a écrit :On Sunday, 5 February 2017 at 14:59:04 UTC, Xavier Bigand wrote:Nice, thank you for that, it is much elegant ;-)Hi, I am trying to create an allocator that don't use the GC, and I have issues for the initialization of member before calling the constructor. Here is my actual code :The whole thing you do to initialize could be replaced by a copy of the initializer, which is what emplace does: static T nogcNew(T, Args...)(Args args) nogc { import core.stdc.stdlib : malloc; import std.traits, std.meta; T instance; enum s = __traits(classInstanceSize, T); instance = cast(T) malloc(s); (cast(void*) instance)[0..s] = typeid(T).initializer[]; instance.__ctor(args); return instance; }mixin template NogcAllocator(T) { static T nogcNew(T, Args...)(Args args) nogc { import core.stdc.stdlib : malloc; import std.traits; T instance; instance = cast(T)malloc(__traits(classInstanceSize, T)); foreach (string member; __traits(allMembers, T)) { static if (isType!(__traits(getMember, T, member))) __traits(getMember, instance, member) = typeof(__traits(getMember, T, member)).init; } instance.__ctor(args); return instance; } static void nogcDelete(T)(T instance) nogc { import core.stdc.stdlib : free; instance.__dtor(); free(instance); } } unittest { struct Dummy { int field1 = 10; int field2 = 11; } class MyClass { mixin NogcAllocator!MyClass; int a = 0; int[] b = [1, 2, 3]; Dummy c = Dummy(4, 5); int d = 6; this() nogc { } this(int val) nogc { d = val; } } MyClass first = MyClass.nogcNew!MyClass(); MyClass second = MyClass.nogcNew!MyClass(7); assert(first.a == 0); assert(first.b == [1, 2, 3]); assert(first.c.field1 == 4); assert(first.d == 6); assert(second.c.field1 == 4); assert(second.d == 7); }And the compilation errors :..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(63): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClass).nogcNew!(MyClass) error instantiating ..\src\core\nogc_memory.d(16): Error: no property 'this' for type 'core.nogc_memory.__unittestL39_3.MyClass' ..\src\core\nogc_memory.d(17): Error: type Monitor is not an expression ..\src\core\nogc_memory.d(64): Error: template instance core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClass).nogcNew!(MyClass, int) error instantiatingI don't understand my mistake with the getMember and isType traits. And I am curious about of what is the Monitor.Your nogcDelete() is bug-prone & leakyCertainly I didn't think a lot about it for the moment.- use _xdtor, which also calls the __dtor injected by mixin. - even if you do so, __xdtors are not inherited !! instead dtor in parent classes are called by destroy() directly. Currently what I do to simulate inherited destructor is to mix this for each new generation. mixin template inheritedDtor() { private: import std.traits: BaseClassesTuple; alias B = BaseClassesTuple!(typeof(this)); enum hasDtor = __traits(hasMember, typeof(this), "__dtor"); static if (hasDtor && !__traits(isSame, __traits(parent, typeof(this).__dtor), typeof(this))) enum inDtor = true; else enum inDtor = false; public void callInheritedDtor(classT = typeof(this))() { import std.meta: aliasSeqOf; import std.range: iota; foreach(i; aliasSeqOf!(iota(0, B.length))) static if (__traits(hasMember, B[i], "__xdtor")) { mixin("this." ~ B[i].stringof ~ ".__xdtor;"); break; } } static if (!hasDtor || inDtor) public ~this() {callInheritedDtor();} } When a dtor is implemented it has to call "callInheritedDtor()" at end of the dtor implementation.Thank you a lot for this great help.
Feb 05 2017