all groups > dotnet clr > july 2004 >
You're in the

dotnet clr

group:

GC SuppressFinalize and ReRegisterForFinalize


GC SuppressFinalize and ReRegisterForFinalize Priyesh
7/25/2004 12:11:35 PM
dotnet clr: I am having trouble understanding the code below.
(From http://msdn.microsoft.com/msdnmag/issues/1100/GCI/ Figure 9)

I am looking for an explanation about how the SuppressFinalize calls work.
From reading the documentation, i get the idea that SuppressFinalize would
remove the obj from the finalization table, so wouldnt it remove all the
entries for a obj as i am operating on the same object? If it toggles a flag
on the obj, how come finalize gets called two times?

void method() {
// The MyObj type has a Finalize method defined for it
// Creating a MyObj places a reference to obj on the finalization table.
MyObj obj = new MyObj();

// Append another 2 references for obj onto the finalization table.
GC.ReRegisterForFinalize(obj);
GC.ReRegisterForFinalize(obj);

// There are now 3 references to obj on the finalization table.

// Have the system ignore the first call to this object's Finalize
// method.
GC.SuppressFinalize(obj);

// Have the system ignore the first call to this object's Finalize
// method.
GC.SuppressFinalize(obj); // In effect, this line does absolutely
// nothing!

obj = null; // Remove the strong reference to the object.

// Force the GC to collect the object.
GC.Collect();

// The first call to obj's Finalize method will be discarded but
// two calls to Finalize are still performed.
}

RE: GC SuppressFinalize and ReRegisterForFinalize clyon NO[at]SPAM online.microsoft.com (
7/27/2004 12:04:38 AM
Hi Priyesh

In the article you point to, Jeffrey explains that SuppressFinalize sets a flag in the object to not run the finalizer. So if you have 3 references to the same object on the finalization
queue, the GC will set the bit when it reaches that object on the queue, then discard it. After that, when the GC reaches the object a second time onthe queue, the flag gets reset
"this flag is reset when the runtime determines that it's time to call a Finalize method", so that's why the finalizer is run twice in the sample you provided.

That being said, I can't think of a valid scenario when someone would want to reregister a live object, so I don't expect this scenario cropping up much in real life.

Also, for what it's worth, that article is pretty outdated, and contains some inaccurate information. For example, it's not possible to override Finalize in C#, and it's impossible to
explicitly call an object's Finalization method. Also, an object's parent's finalizer is called automatically (check out the IL to see for yourself).

Hope that helps
-Chris


--------------------
[quoted text, click to view]


--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.
Re: GC SuppressFinalize and ReRegisterForFinalize Priyesh
7/27/2004 7:20:18 AM
Thanks for your explanation and the points about the correctness of the
article. I understand that this is a theoretical scenario to explain some of
the GC functionality available.

I was thinking that there is some sort of reference counting mechanism for
the same object in the finalization queue. Since the example operates on a
single object, i got myself into thinking SuppressFinalize call on that
object would affect that one object and would not let any further Finalize
calls. From your explanation, it seems that the finalization queue contains
a separate structure which has a pointer to the object to be finalized.

When ReRegisterForFinalize is called on an object, is there another memory
structure created in the finalization queue?
If so, how does the SuppressFinalize determine which reference in the queue
to apply the suppress to? (Does it apply to the first reference in queue all
the time?)
Is there a way to get rid of all pending finalization requests?

I would really appreciate your follow up on these questions.



[quoted text, click to view]
flag in the object to not run the finalizer. So if you have 3 references to
the same object on the finalization
[quoted text, click to view]
then discard it. After that, when the GC reaches the object a second time
onthe queue, the flag gets reset
[quoted text, click to view]
Finalize method", so that's why the finalizer is run twice in the sample you
provided.
[quoted text, click to view]
to reregister a live object, so I don't expect this scenario cropping up
much in real life.
[quoted text, click to view]
some inaccurate information. For example, it's not possible to override
Finalize in C#, and it's impossible to
[quoted text, click to view]
parent's finalizer is called automatically (check out the IL to see for
yourself).
[quoted text, click to view]
message are best directed to the newsgroup/thread from which they
originated.
[quoted text, click to view]

Re: GC SuppressFinalize and ReRegisterForFinalize Priyesh
7/27/2004 10:51:38 AM
Hi Chris,
Thanks for the reply. Here is what i understand from your explanation.

1. The finalization queue will keep on adding references to the same object
to match ReRegisterForFinalize calls on the same object.

2. SuppressFinalize will set the "run my finalizer bit" in the obj. When GC
reaches a reference
in the finalization queue, it checks this bit and if the bit is not set,
wont move that to the f-reachable. GC would set the bit on the object so
that the object references pending in the finalization queue will be moved
to f-reachable and eventually the Finalize method will be called.

Please tell me if i understood it right.

Thanks
Priyesh

[quoted text, click to view]
SuppressFinalize(obj) affects the first reference to obj on the queue, so
calling it several times in a row has
[quoted text, click to view]
(strong) reference to the object in memory. In the object's header is the
"run my finalizer" bit. When
[quoted text, click to view]
the first reference to obj (when called again, it starts from the front of
the queue again). That bit is set
[quoted text, click to view]
obj, another reference to the object is placed at the end of the (FIFO)
queue), so Suppress will never reach
[quoted text, click to view]
have a suppress after every call to reregister. Short of that, maybe
setting a flag in your finalizer to say
[quoted text, click to view]
cpmsftngxa10.phx.gbl!TK2MSFTFEED01.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12
..phx.gbl
[quoted text, click to view]
Re: GC SuppressFinalize and ReRegisterForFinalize Priyesh
7/27/2004 4:10:41 PM
Thankyou. I really appreciate it.

[quoted text, click to view]
that reference is removed from the queue, at which point the GC resets the
bit to true. Now when the next
[quoted text, click to view]
Re: GC SuppressFinalize and ReRegisterForFinalize clyon NO[at]SPAM online.microsoft.com (
7/27/2004 4:28:19 PM
Hi Priyesh

No, there's no reference counting involved on the finalization queue. SuppressFinalize(obj) affects the first reference to obj on the queue, so calling it several times in a row has
no added effect, regardless of how many times obj is on the queue.

The finalization queue doesn't have a seperate structure, rather a (strong) reference to the object in memory. In the object's header is the "run my finalizer" bit. When
suppressis called, the GC scans the queue from the front and and stops at the first reference to obj (when called again, it starts from the front of the queue again). That bit is set
in the header of the object obj points to. When reregister is called on obj, another reference to the object is placed at the end of the (FIFO) queue), so Suppress will never reach
past the first reference (which is why, as Richter states, you cannot balance out several calls to Rereg with Suppress).

The only I can think of to remove all pending finalization requestsis to have a suppress after every call to reregister. Short of that, maybe setting a flag in your finalizer to say
your object has already been finalized would remove redundant cleanup, but wouldn't stop the object from being put on the queue.

Hope that helps
-Chris


--------------------
[quoted text, click to view]
Re: GC SuppressFinalize and ReRegisterForFinalize clyon NO[at]SPAM online.microsoft.com (
7/27/2004 10:12:03 PM
Hi Priyesh

1. Yes, that's right.

2. Yes. SuppressFinalizer sets the "run my finalizer" bit to false, and that reference is removed from the queue, at which point the GC resets the bit to true. Now when the next
reference to the same object is encountered on the queue, the object is moved to the f-reachable queue where its finalizer gets run.

I think we're on the same page now :)

-Chris

--------------------

[quoted text, click to view]
AddThis Social Bookmark Button