www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Finalize GC memory

reply "Namespace" <rswhite4 googlemail.com> writes:
With the knowledge that 'delete' will be deprecated soon:
Is there then still a way to finalize GC memory? I know it's 
unsafe etc. but is there a way? I know of 'destroy' but it does 
not finalize anything and AFAIK it's not safe and has also side 
effects. And it does not call the DTor if any struct is allocated 
with 'new'.
I tried GC.free, GC.collect, destroy and a few other things, but 
except of 'delete' nothing finalize the memory.
Thoughts?
Jun 15 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
I assume the silence means no?
Jun 16 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/15/2013 02:22 PM, Namespace wrote:

 With the knowledge that 'delete' will be deprecated soon:
 Is there then still a way to finalize GC memory? I know it's unsafe etc.
 but is there a way? I know of 'destroy' but it does not finalize
 anything and AFAIK it's not safe and has also side effects.
Being a C++ programmer, I am new to the term "finalize". If it means "call the destructor", then destroy() is it.
 And it does
 not call the DTor if any struct is allocated with 'new'.
It does: import std.stdio; struct S { ~this() { writeln("destructor called"); } } void main() { auto s = new S(); destroy(*s); // NOTE the '*' operator! }
 I tried GC.free, GC.collect, destroy and a few other things, but except
 of 'delete' nothing finalize the memory.
 Thoughts?
Ali
Jun 16 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 Being a C++ programmer, I am new to the term "finalize". If it 
 means "call the destructor", then destroy() is it.
Finalize -> free the memory immediately as 'delete' it does currently.
 And it does
 not call the DTor if any struct is allocated with 'new'.
It does: import std.stdio; struct S { ~this() { writeln("destructor called"); } } void main() { auto s = new S(); destroy(*s); // NOTE the '*' operator! }
Good to know!
Jun 16 2013
parent "Namespace" <rswhite4 googlemail.com> writes:
I have adjusted the thread title.
Jun 16 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, June 16, 2013 12:24:40 Ali =C3=87ehreli wrote:
 On 06/15/2013 02:22 PM, Namespace wrote:
  > With the knowledge that 'delete' will be deprecated soon:
  > Is there then still a way to finalize GC memory? I know it's unsaf=
e etc.
  > but is there a way? I know of 'destroy' but it does not finalize
  > anything and AFAIK it's not safe and has also side effects.
=20
 Being a C++ programmer, I am new to the term "finalize". If it means
 "call the destructor", then destroy() is it.
http://en.wikipedia.org/wiki/Finalizer It's basically just means calling the finalizer, and D conflates finali= zers and=20 destructors, so the destructor of any object on the GC heap is that obj= ect's=20 finalizer. Normally, it's called when the object is collected, but it c= an get a=20 bit messy depending on how the GC works. It's essentially a non-determi= nstic=20 destructor though. - Jonathan M Davis
Jun 16 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 http://en.wikipedia.org/wiki/Finalizer

 It's basically just means calling the finalizer, and D 
 conflates finalizers and
 destructors, so the destructor of any object on the GC heap is 
 that object's
 finalizer. Normally, it's called when the object is collected, 
 but it can get a
 bit messy depending on how the GC works. It's essentially a 
 non-determinstic
 destructor though.

 - Jonathan M Davis
It was my fault. What I meant was to release GC memory immediately.
Jun 16 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
It seems that does what I want. The result is the same as with 
the current 'delete' implementation.

----
void Delete(T)(ref T var) {
	static if (is(T == struct) && is(typeof(var.__dtor)))
		var.__dtor();
		
	static if (is(T : U[], U))
		core.memory.GC.free(var.ptr);
	else {
		static if (is(T : U*, U))
			core.memory.GC.free(var);
		else
			core.memory.GC.free(&var);
	}
}
----

But if I call 'destroy' before I call GC.free, it does not work 
correct.
Jun 16 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Sunday, 16 June 2013 at 21:37:16 UTC, Namespace wrote:
 It seems that does what I want. The result is the same as with 
 the current 'delete' implementation.

 ----
 void Delete(T)(ref T var) {
 	static if (is(T == struct) && is(typeof(var.__dtor)))
 		var.__dtor();
 		
 	static if (is(T : U[], U))
 		core.memory.GC.free(var.ptr);
 	else {
 		static if (is(T : U*, U))
 			core.memory.GC.free(var);
 		else
 			core.memory.GC.free(&var);
 	}
 }
 ----

 But if I call 'destroy' before I call GC.free, it does not work 
 correct.
I forget 'var = null;'. But: Any thoughts on this? Will it work as I want? In my few tests it seems to work like delete, but I would be interested in the meaning of some experts.
Jun 17 2013
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, June 17, 2013 18:46:29 Namespace wrote:
 On Sunday, 16 June 2013 at 21:37:16 UTC, Namespace wrote:
 It seems that does what I want. The result is the same as with
 the current 'delete' implementation.
 
 ----
 void Delete(T)(ref T var) {
 
 static if (is(T == struct) && is(typeof(var.__dtor)))
 
 var.__dtor();
 
 static if (is(T : U[], U))
 
 core.memory.GC.free(var.ptr);
 
 else {
 
 static if (is(T : U*, U))
 
 core.memory.GC.free(var);
 
 else
 
 core.memory.GC.free(&var);
 
 }
 
 }
 ----
 
 But if I call 'destroy' before I call GC.free, it does not work
 correct.
I forget 'var = null;'. But: Any thoughts on this? Will it work as I want? In my few tests it seems to work like delete, but I would be interested in the meaning of some experts.
I'd be worried about whether it actually called the destructors of the members of the struct. IIRC, you actually have to play around with TypeInfo in order to be able to correctly manually destroy a struct rather than simply calling its __dtor method, but it's not something that I ever do, so I don't remember the details. Regardless, if destroy doesn't actually destroy a struct correctly, then that's a bug and should be reported. - Jonathan M Davis
Jun 17 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 I'd be worried about whether it actually called the destructors 
 of the members
 of the struct. IIRC, you actually have to play around with 
 TypeInfo in order
 to be able to correctly manually destroy a struct rather than 
 simply calling
 its __dtor method, but it's not something that I ever do, so I 
 don't remember
 the details. Regardless, if destroy doesn't actually destroy a 
 struct
 correctly, then that's a bug and should be reported.

 - Jonathan M Davis
Why the members could not be destroyed? Could you give me an example? And did you have a link, that explain how I should use TypeInfo to destroy the struct correctly?
Jun 18 2013
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 18 Jun 2013 03:59:37 -0400, Namespace <rswhite4 googlemail.com>  
wrote:

 I'd be worried about whether it actually called the destructors of the  
 members
 of the struct. IIRC, you actually have to play around with TypeInfo in  
 order
 to be able to correctly manually destroy a struct rather than simply  
 calling
 its __dtor method, but it's not something that I ever do, so I don't  
 remember
 the details. Regardless, if destroy doesn't actually destroy a struct
 correctly, then that's a bug and should be reported.

 - Jonathan M Davis
Why the members could not be destroyed? Could you give me an example? And did you have a link, that explain how I should use TypeInfo to destroy the struct correctly?
Be careful what hidden members you call, some of them are not what you think they are. As a guide, you should take a look at the destroy function in object to see the proper method of destroying things. -Steve
Jun 18 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 Be careful what hidden members you call, some of them are not 
 what you think they are.
For example?
 As a guide, you should take a look at the destroy function in 
 object to see the proper method of destroying things.

 -Steve
Jun 18 2013
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 18 Jun 2013 09:34:44 -0400, Namespace <rswhite4 googlemail.com>  
wrote:

 Be careful what hidden members you call, some of them are not what you  
 think they are.
For example?
For example, __dtor may not be the full destructor, but just the code represented by ~this(). I think this is the case for structs. I have a bug report somewhere, let me see... Oops, not my bug, but I commented on it :) See comment 6 from Kenji: http://d.puremagic.com/issues/show_bug.cgi?id=5667#c6 -Steve
Jun 18 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
I must ask again:

  -> The block will not be finalized regardless of whether the 
FINALIZE attribute is set. If finalization is desired, use delete 
instead.

In knowledge of this: How can I *finalize* GC memory? delete is 
or will be deprecated soon.
Jul 04 2013
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 16 Jun 2013 17:37:15 -0400, Namespace <rswhite4 googlemail.com>  
wrote:

 But if I call 'destroy' before I call GC.free, it does not work correct.
Destroy puts anything back into it's initial state. So for anything that is a pointer, destroy will set it to null! Then calling GC free on null is no good. What you have to do is save a copy of the pointer, to pass to GC.free later. -Steve
Jun 17 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Monday, 17 June 2013 at 17:09:45 UTC, Steven Schveighoffer 
wrote:
 On Sun, 16 Jun 2013 17:37:15 -0400, Namespace 
 <rswhite4 googlemail.com> wrote:

 But if I call 'destroy' before I call GC.free, it does not 
 work correct.
Destroy puts anything back into it's initial state. So for anything that is a pointer, destroy will set it to null! Then calling GC free on null is no good. What you have to do is save a copy of the pointer, to pass to GC.free later. -Steve
Ok, thanks. And you think that my code is working as intended? Or have I overlooked something obvious.
Jun 17 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
Here my new version:
----
void Delete(T)(ref T var) if (isAssignable!(T, typeof(null)) && 
!isStaticArray!T) {
	const bool isPtr = is(T : U*, U);

	static if (isPtr && (is(U == struct) || is(U == class)))
		.destroy(*var);

	static if (is(T : U[], U))
		GC.free(var.ptr);
	else {
		static if (isPtr)
			GC.free(var);
		else
			GC.free(&var);
	}

	var = null;
}
----

That should fulfill all wishes. :)
Jun 18 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Namespace:

 Here my new version:
 ----
 void Delete(T)(ref T var) if (isAssignable!(T, typeof(null)) && 
 !isStaticArray!T) {
 ...
 ----

 That should fulfill all wishes. :)
Its name should start with a lowercase, according to the D style. Bye, bearophile
Jun 18 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Tuesday, 18 June 2013 at 09:16:05 UTC, bearophile wrote:
 Namespace:

 Here my new version:
 ----
 void Delete(T)(ref T var) if (isAssignable!(T, typeof(null)) 
 && !isStaticArray!T) {
 ...
 ----

 That should fulfill all wishes. :)
Its name should start with a lowercase, according to the D style. Bye, bearophile
Maybe, but 'delete' is already a keyword and 'destroy' already exists.
Jun 18 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Just for you:
http://dpaste.1azy.net/3b46c669

This code works now perfect and works also with forward 
referenced opaque structures.
Jun 18 2013