The first statement is correct, but it is actually done at the time of object creation
Hi Senthil,
I was trying understand this statement and wanted to ensure i do not send any wrong information. what i understand is if the objects are created they are first moved to gen 0 pool. The decision of moving to the Finalization queue is only done by GC. In other words its only done when the GC runs. Any pointers where i can understand this statement much better.
Waiting for your reply. Sorry to invade your privacy , can i get your email address so that i can communicate more effectively ?.
Visit my 500 videos on WCF,WPF,WWF,Silverlight,UML design patters @ http://www.questpond.com
The decision of moving to the Finalization queue is only done by GC.
Moving the reference to the freachable queue is done by the GC.
Let's say you have an object of a type with a finalizer. You create that object, call methods on it, and discard the reference. At the time of garbage collection, how will the collector know whether this object has a finalizer?
It can look into the metadata for that type to figure it out, but then this increases the cost of garbage collection, even if none of the objects in the heap have a finalizer. Instead, a reference to the object is put in a separate container, the finalization queue. The finalization queue acts as a root for the purposes of GC, so according to the GC, the object still has a reference, and so it cannot be collected. The GC also now knows that this object has a finalizer, because it's referred from the finalization queue, so if there are no other references, it moves it to the freachable queue.
Jeffrey Richter describes this quite clearly in this[^] article.
" When an application creates a new object, the new operator allocates the memory from the heap. If the object's type contains a Finalize method, then a pointer to the object is placed on the finalization queue...."
The finalization queue acts as a root for the purposes of GC, so according to the GC, the object still has a reference, and so it cannot be collected.
This might be an inaccurate statement.
Finalization queue should NOT act as a root. This is just a place where maintains addresses of objects those who contains a Finalize method (no matter they are reachable or unreachable). So there is no reason to make finalization queue as a root.
But once they where moved from finalization queue to freachable queue. For the reason that the freachable queue is proceeded by another thread when entries appear, to prevent those objects from being collected while this thread is executing their Finalize methods, they made objects in freachable queue as roots.
This is also how it got its name. The "f" stands for having Finalize method. The "reachable" stands for all objects in this queue are reachable (by making them roots).
So the correct statement might be:
The freachable queue acts as a root (but the finalization queue does not).
If it is not a root, how would the GC know not to collect finalizable objects, as there would be no other references to them?
I'd imagine there would be conceptually two separate phases during GC - collection and compaction, and moving references from the finalizable queue to the freachable queue. In the first phase, the GC has to treat the finalizable queue as a root, or it would end up collecting finalizable objects also.
Without having read your article in-depth (you may already have covered this?) - I would like to give my 2 cents.
I have been working with this pattern alot myself, and have come across an issue that one has to take into account when writing their "CleanUp"-code:
The sequence of which the "Finalize" method is called is non-deterministic:
1) Say you have object A that is referencing object B
2) object A's CleanUp() calls Dispose on object B
With the above design - you may experience that the garbage collector chooses to call Finalize on object B before object A even though object A reference object B.
Solution: Always check whether or not your object has already been disposed in your "CleanUp"-code.
/Michael
Need a 0 false positive SPAM filter? Try the free, industry leading spam filters from SPAMfighter
With the above design - you may experience that the garbage collector chooses to call Finalize on object B before object A even though object A reference obj
Which is why the standard pattern has a disposed flag, which allows you to distinguish Dispose calls from finalizer calls. If the call is from the finalizer, you can skip cleanup of managed objects implementing a finalizer.
I agree to your comments and i have updated the code with the disposing flag. I was trying to provide a more shorter way. But then i realized performance can not have shortcuts.
Yes, the GC is such a undetermestic beast a flag is essential.
Let me know if the code is fine.
Visit my 500 videos on WCF,WPF,WWF,Silverlight,UML design patters @ http://www.questpond.com
There are however a few items that I have been unable to fully grasp despite a lot of searching on the net and as you obviously have the gift of providing understandable explanations of otherwise complex issues, I wonder if you could expand on:
1. Destructors.
Exactly what does a destructor do? I would have guessed it destructs everything constructed within the class but obviously not. The destructor appears almost in no class that I have ever come accross on the net.
2. CleanUp().
What has to be 'cleaned up'. All anyone says is 'unmanaged code' but what exactly is unmanaged code? I found out about static variables the hard way.
3. GC.SuppressFinalize(this)
If I forget to CleanUp() some 'item', will it never be 'collected' by the GC?
I appreciate the above is not actually part of your article however it would help me to understand your article much better and put to bed some matters that have been baffling me for a long time.
1. Destructors.
Some good info available at these threads
http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/f73ad923-ffd5-4f16-a0bf-1f27b71f952f
In short there is no need for a default destructor unless you are dealing with these unmanaged objects.
2. CleanUP()
Some examples of unmanaged resources are network connections, file streams, database connection etc.
3. GC.SuppressFinalize(this)
The stackoverflow.com has some good responses to this...
http://stackoverflow.com/questions/151051/when-should-i-use-gc-suppressfinalize
These are not direct answers to your questions but just some pointers for reference.
1 - In C#, a destructor will be compiled into Finalize() method. Destructor is used to perform resource cleanup. You need destructors only in those classes that has some resources to cleanup. MSDN says, finalization is costly and you should avoid it if possible.
Any class that holds other disposable objects or work directly with unmanaged code is a good candidate for writing destructor and implementing dispose pattern.
2 - Any resource an object holds should be cleaned up once done. If your class holds some resources that needs clean-up, you should write destructor and implement IDispose interface. Writing Dispose() method is for deterministic resource clean-up and destructor is for garbage collector.
Un-managed code is something that CLR won't have control. For e.g: P/Invoke call to a native library.
3 - GC.SuppressFinalize() will suppress the execution of finalize methods. This is useful when you have already cleaned-up the resources by calling dispose.
Glen Harvy wrote:
If I forget to CleanUp() some 'item', will it never be 'collected' by the GC?
Depends on what kind of resources your class holds. Consider the following class,
class Logger
{
FileStream stream = /* ... */// Other code
}
In this case, even if you forgot to call dispose on stream , it will get collected when nothing is referring the variable. But this is not the case when you use a handle directly. In such cases, you need to explicitly remove it and GC can't clean it.
Probably i should have put a pre-requiste about what should be know before reading this article. My main focus was on the issues of perfomance hit due to GC.
For the coming articles i will try to keep pointers for beginners as well.
Visit my 500 videos on WCF,WPF,WWF,Silverlight,UML design patters @ http://www.questpond.com
I appreciate that your article was intended to discuss performance but with a couple more well written sentences (for which you appear to have the skills), the article would have been self-contained and would have provided me with all I needed to know on the subject.
It is difficult to discuss technical isues without using jargon however I do believe many articles are written to prove how much the author knows, not to provide the answers to the 'student'.
Thank you for your efforts. Keep up the good work.