www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Call destructor directly.

reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
I'm implementing some custom memory allocator, is possible to 
call an object destructor directly?

For example

void deallocate(T)(T object)
{
   assert(object !is null);

   object.~this();
   rawDeallocate(cast(void *)object);
}
Oct 20 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
 I'm implementing some custom memory allocator, is possible to 
 call an object destructor directly?
destroy(object); destroy is in the automatically imported object.dm so you don't have to import anything, The source code is in dmd2/src/druntime/src/object_.d, there's a few overloads if you are curious how it is implemented. Short answer is there's a pointer to the destructor in the TypeInfo and destroy calls it.
Oct 20 2013
next sibling parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 02:17:54 UTC, Adam D. Ruppe wrote:
 On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
 I'm implementing some custom memory allocator, is possible to 
 call an object destructor directly?
destroy(object); destroy is in the automatically imported object.dm so you don't have to import anything, The source code is in dmd2/src/druntime/src/object_.d, there's a few overloads if you are curious how it is implemented. Short answer is there's a pointer to the destructor in the TypeInfo and destroy calls it.
Thank you :)
Oct 20 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 02:26:03 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 02:17:54 UTC, Adam D. Ruppe wrote:
 On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
 I'm implementing some custom memory allocator, is possible to 
 call an object destructor directly?
destroy(object); destroy is in the automatically imported object.dm so you don't have to import anything, The source code is in dmd2/src/druntime/src/object_.d, there's a few overloads if you are curious how it is implemented. Short answer is there's a pointer to the destructor in the TypeInfo and destroy calls it.
Thank you :)
What about constructor?. My current code is: T allocate(T : Object, A...)(auto ref A arguments) { auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); // Return void* emplace!T(cast(T *)pMemory, arguments); return cast(T) pMemory; } Doesn't seems to work, and i can't find any good documentation about it.
Oct 20 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 
 	T allocate(T : Object, A...)(auto ref A arguments) {
 		auto pMemory = rawAllocate(__traits(classInstanceSize, T),
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	}
 
 Doesn't seems to work, and i can't find any good documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
Oct 20 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 03:46:33 UTC, Jonathan M Davis 
wrote:
 On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 
 	T allocate(T : Object, A...)(auto ref A arguments) {
 		auto pMemory = rawAllocate(__traits(classInstanceSize, T),
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	}
 
 Doesn't seems to work, and i can't find any good documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
no property 'opCall' for type 'Main.MyClass' :(
Oct 20 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 03:50:24 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 03:46:33 UTC, Jonathan M Davis 
 wrote:
 On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 
 	T allocate(T : Object, A...)(auto ref A arguments) {
 		auto pMemory = rawAllocate(__traits(classInstanceSize, T),
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	}
 
 Doesn't seems to work, and i can't find any good documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
no property 'opCall' for type 'Main.MyClass' :(
Trait allMember return "__ctor", but seems like i cannot call it directly: (cast(T)pMemory).__ctor(arguments); // Being pMemory void*
Oct 20 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, October 21, 2013 05:53:46 Agustin wrote:
 On Monday, 21 October 2013 at 03:50:24 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 03:46:33 UTC, Jonathan M Davis
 
 wrote:
 On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 	T allocate(T : Object, A...)(auto ref A arguments) {
 	
 		auto pMemory = rawAllocate(__traits(classInstanceSize, T),
 
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	
 	}
 
 Doesn't seems to work, and i can't find any good documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
no property 'opCall' for type 'Main.MyClass' :(
Trait allMember return "__ctor", but seems like i cannot call it directly: (cast(T)pMemory).__ctor(arguments); // Being pMemory void*
If you want to see how to use emplace, I'd advise looking at std.typecons.RefCounted's implementation: https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L3505 emplace calls the constructor for you, so I don't know why you'd be trying to call it. But you can look at emplace's implementation if you want to see how to call __ctor. For structs: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L3976 For classes: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L4716 I don't think that it'll work if the constructor is private though, so maybe that's your problem. - Jonathan M Davis
Oct 20 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 05:17:01 UTC, Jonathan M Davis 
wrote:
 On Monday, October 21, 2013 05:53:46 Agustin wrote:
 On Monday, 21 October 2013 at 03:50:24 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 03:46:33 UTC, Jonathan M Davis
 
 wrote:
 On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 	T allocate(T : Object, A...)(auto ref A arguments) {
 	
 		auto pMemory = rawAllocate(__traits(classInstanceSize, 
 T),
 
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	
 	}
 
 Doesn't seems to work, and i can't find any good 
 documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
no property 'opCall' for type 'Main.MyClass' :(
Trait allMember return "__ctor", but seems like i cannot call it directly: (cast(T)pMemory).__ctor(arguments); // Being pMemory void*
If you want to see how to use emplace, I'd advise looking at std.typecons.RefCounted's implementation: https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L3505 emplace calls the constructor for you, so I don't know why you'd be trying to call it. But you can look at emplace's implementation if you want to see how to call __ctor. For structs: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L3976 For classes: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L4716 I don't think that it'll work if the constructor is private though, so maybe that's your problem. - Jonathan M Davis
I'm silly the issue was at this line auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); emplace(pMemory, arguments); Correct was auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); emplace(&pMemory, arguments); Thanks guys
Oct 20 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 05:40:13 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 05:17:01 UTC, Jonathan M Davis 
 wrote:
 On Monday, October 21, 2013 05:53:46 Agustin wrote:
 On Monday, 21 October 2013 at 03:50:24 UTC, Agustin wrote:
 On Monday, 21 October 2013 at 03:46:33 UTC, Jonathan M Davis
 
 wrote:
 On Monday, October 21, 2013 05:07:02 Agustin wrote:
 What about constructor?. My current code is:
 	T allocate(T : Object, A...)(auto ref A arguments) {
 	
 		auto pMemory = rawAllocate(__traits(classInstanceSize, 
 T),
 
 T.alignof); // Return void*
 
 		emplace!T(cast(T *)pMemory, arguments);
 		return cast(T) pMemory;
 	
 	}
 
 Doesn't seems to work, and i can't find any good 
 documentation
 about it.
IIRC, the constructor should be name __ctor. - Jonathan M Davis
no property 'opCall' for type 'Main.MyClass' :(
Trait allMember return "__ctor", but seems like i cannot call it directly: (cast(T)pMemory).__ctor(arguments); // Being pMemory void*
If you want to see how to use emplace, I'd advise looking at std.typecons.RefCounted's implementation: https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L3505 emplace calls the constructor for you, so I don't know why you'd be trying to call it. But you can look at emplace's implementation if you want to see how to call __ctor. For structs: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L3976 For classes: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L4716 I don't think that it'll work if the constructor is private though, so maybe that's your problem. - Jonathan M Davis
I'm silly the issue was at this line auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); emplace(pMemory, arguments); Correct was auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); emplace(&pMemory, arguments); Thanks guys
That didn't work, but after reading how emplace works, i had to make some changes. public T allocate(T : Object, A...)(auto ref A arguments) { auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); assert(pMemory !is null, "Not enought memory on the allocator"); byte[] * pByteMemory = cast(byte[] *) pMemory; *pByteMemory = typeid(T).init[]; auto pObject = cast(T) pMemory; static if (is(typeof(pObject.__ctor(arguments)))) { pObject.__ctor(arguments); } return pObject; } That would work.
Oct 20 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 10/20/2013 10:59 PM, Agustin wrote:

 That didn't work, but after reading how emplace works, i had to make
 some changes.

      public T allocate(T : Object, A...)(auto ref A arguments) {
          auto pMemory = rawAllocate(__traits(classInstanceSize, T),
 T.alignof);
Does rawAllocate still return void*? For classes, emplace requires (or at least "also accepts" a slice). Your code will be simpler if rawAllocate returned a slice: import std.conv; void[] rawAllocate(size_t, size_t) { static ubyte[1000] buffer; return buffer; } T allocate(T : Object, A...)(auto ref A arguments) { auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); return emplace!T(pMemory, arguments); } class C { this(int i, double d) {} } void main() { auto c = allocate!C(42, 1.5); } If it has to return void*, you can make a slice from a plain pointer with the following syntax: void * rawAllocate(size_t, size_t) { static ubyte[1000] buffer; return buffer.ptr; } import std.stdio; void main() { enum requiredLength = 42; auto rawPtr = rawAllocate(requiredLength, 16); auto slice = rawPtr[0..requiredLength]; // <-- slice from plain pointer writeln(slice); } Ali
Oct 21 2013
parent "Agustin" <agustin.l.alvarez hotmail.com> writes:
On Monday, 21 October 2013 at 07:31:30 UTC, Ali Çehreli wrote:
 On 10/20/2013 10:59 PM, Agustin wrote:

 That didn't work, but after reading how emplace works, i had
to make
 some changes.

      public T allocate(T : Object, A...)(auto ref A
arguments) {
          auto pMemory =
rawAllocate(__traits(classInstanceSize, T),
 T.alignof);
Does rawAllocate still return void*? For classes, emplace requires (or at least "also accepts" a slice). Your code will be simpler if rawAllocate returned a slice: import std.conv; void[] rawAllocate(size_t, size_t) { static ubyte[1000] buffer; return buffer; } T allocate(T : Object, A...)(auto ref A arguments) { auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof); return emplace!T(pMemory, arguments); } class C { this(int i, double d) {} } void main() { auto c = allocate!C(42, 1.5); } If it has to return void*, you can make a slice from a plain pointer with the following syntax: void * rawAllocate(size_t, size_t) { static ubyte[1000] buffer; return buffer.ptr; } import std.stdio; void main() { enum requiredLength = 42; auto rawPtr = rawAllocate(requiredLength, 16); auto slice = rawPtr[0..requiredLength]; // <-- slice from plain pointer writeln(slice); } Ali
Thanks!, i didn't knew i could do that, void[] sounds like an array of nothing :P. On Monday, 21 October 2013 at 11:48:11 UTC, Benjamin Thaut wrote:
 Am 21.10.2013 04:17, schrieb Adam D. Ruppe:
 On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
 I'm implementing some custom memory allocator, is possible to 
 call an
 object destructor directly?
destroy(object); destroy is in the automatically imported object.dm so you don't have to import anything, The source code is in dmd2/src/druntime/src/object_.d, there's a few overloads if you are curious how it is implemented. Short answer is there's a pointer to the destructor in the TypeInfo and destroy calls it.
Using destroy will zero the entire memory block after destroying the object. If you are freeing the memory right after destroying this is going to cost you performance. To avoid this declare: extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true); and then call rt_finalize(cast(void*)object, false, false); Also if you want to give a nice error message in case you are calling a construcor that does not exist you should take a look at my AllocatorNew function: https://github.com/Ingrater/druntime/blob/merge64/src/core/allocator.d#L616 Doing it the way emplace does will just result in a error message "Dont know how to initialize a object of type YourObject" With some meta programming you can get error messages like: "Dont know how to initialize a object of type YourObject Available constructors: this(int, int) this(float) this(void*)" Kind Regards Benjamin Thaut
I just need to call the destructor of the class since the memory of the allocators is released at the end of the application. // Pre allocate 1GB. auto pMemory = GC.malloc(1_048_576 * 1000, GC.BlkAttr.NONE); // Allocate a linear allocator of 10MB. auto pLinearAllocator = new LinearAllocator(1_048_576 * 10, pMemory); // Allocates a pool allocator of 50MB. auto pMemoryBlock = pMemory + 1_048_576 * 10; auto pPoolAllocator = new PoolAllocator!MyComponent(1_048_576 * 50, pMemory + 1_048_576 * 10); // Game loop, etc. // ..... (When a object is called to release, it won't release its memory rather than cache the entry and call the object destructor. Releasing the object from GC // end of game exit() // Allocators are released here, because GC will not find any reference to it, and will call any object destructor left.
Oct 21 2013
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 21.10.2013 04:17, schrieb Adam D. Ruppe:
 On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
 I'm implementing some custom memory allocator, is possible to call an
 object destructor directly?
destroy(object); destroy is in the automatically imported object.dm so you don't have to import anything, The source code is in dmd2/src/druntime/src/object_.d, there's a few overloads if you are curious how it is implemented. Short answer is there's a pointer to the destructor in the TypeInfo and destroy calls it.
Using destroy will zero the entire memory block after destroying the object. If you are freeing the memory right after destroying this is going to cost you performance. To avoid this declare: extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true); and then call rt_finalize(cast(void*)object, false, false); Also if you want to give a nice error message in case you are calling a construcor that does not exist you should take a look at my AllocatorNew function: https://github.com/Ingrater/druntime/blob/merge64/src/core/allocator.d#L616 Doing it the way emplace does will just result in a error message "Dont know how to initialize a object of type YourObject" With some meta programming you can get error messages like: "Dont know how to initialize a object of type YourObject Available constructors: this(int, int) this(float) this(void*)" Kind Regards Benjamin Thaut
Oct 21 2013
parent "Dicebot" <public dicebot.lv> writes:
On Monday, 21 October 2013 at 11:48:11 UTC, Benjamin Thaut wrote:
 Using destroy will zero the entire memory block after 
 destroying the object. If you are freeing the memory right 
 after destroying this is going to cost you performance.

 To avoid this declare:

 extern (C) void rt_finalize2(void* p, bool det = true, bool 
 resetMemory = true);
It is probably a good idea to use malloc/free for deterministic allocators anyway as GC is not really supposed to be used that way by design.
Oct 21 2013