Idea: GC and IDisposable

H

Hilton

Hi,

I'm sure I'm simplifying things here, but how about if the GC did this to
objects that implement IDisposable:
1. Always Generation 1 (I think that is the correct name)
2. Get aggressive with them:
a. Nuke 'em on a GC.Collect call (or equivalent)
b. Call Dispose on the object.

Yes, I understand that the compiler and the GC doesn't know what IDisposable
is, but surely it is a worthwhile consideration? This garbabe/resource
collection is particularly important in the CF world.

Hilton
 
N

Nicholas Paldino [.NET/C# MVP]

Hilton,

This idea doesn't do much, really. It only serves to reward people for
not being aware of the implementation of their designs.

If you are not aware of the lifespans of the objects that you are using,
then that is an error, either in design, or implementation, or the
understanding of the underlying technologies and it should be fixed. If
something implements IDisposable, that should be a huge red flag that tells
the developer "hey, YOU (not the GC) need to pay extra attention to me, as I
am doing something that you want to pay attention to, and not just leave
lying around."
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Hilton said:
Hi,

I'm sure I'm simplifying things here, but how about if the GC did this to
objects that implement IDisposable:
1. Always Generation 1 (I think that is the correct name)
2. Get aggressive with them:
a. Nuke 'em on a GC.Collect call (or equivalent)
b. Call Dispose on the object.

Yes, I understand that the compiler and the GC doesn't know what IDisposable
is, but surely it is a worthwhile consideration? This garbabe/resource
collection is particularly important in the CF world.

Hilton

The IDisposable interface is intended for the developer to be able to
control the life cycle of an object. That doesn't only mean to kill it
in a predictable way, but sometimes also to keep it alive in a
predictable way.
 
G

Guest

Agreed. Implementing IDisposable is a flag to the consumer, not the GC.
The GC doesn't know or care about IDisposable objects. If it did, then you
would have the issues currently surrounding Finalizers to content with (and
that's the exact reason it's recommended that you implement IDisposable
instead of using a Finalizer).

There's no way to "automate" this process without causing pain for those of
us who like performance or adding the requirement of multiple collection
cycles to release resources.

--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Managed Code in an Embedded World
www.OpenNETCF.com


Nicholas Paldino said:
Hilton,

This idea doesn't do much, really. It only serves to reward people for
not being aware of the implementation of their designs.

If you are not aware of the lifespans of the objects that you are
using, then that is an error, either in design, or implementation, or the
understanding of the underlying technologies and it should be fixed. If
something implements IDisposable, that should be a huge red flag that
tells the developer "hey, YOU (not the GC) need to pay extra attention to
me, as I am doing something that you want to pay attention to, and not
just leave lying around."


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hilton said:
Hi,

I'm sure I'm simplifying things here, but how about if the GC did this to
objects that implement IDisposable:
1. Always Generation 1 (I think that is the correct name)
2. Get aggressive with them:
a. Nuke 'em on a GC.Collect call (or equivalent)
b. Call Dispose on the object.

Yes, I understand that the compiler and the GC doesn't know what
IDisposable is, but surely it is a worthwhile consideration? This
garbabe/resource collection is particularly important in the CF world.

Hilton
 
B

Ben Voigt [C++ MVP]

The IDisposable interface is intended for the developer to be able to
control the life cycle of an object. That doesn't only mean to kill it in
a predictable way, but sometimes also to keep it alive in a predictable
way.

Exactly. I sure wouldn't like all my Form and Control-derived objects being
disposed on every GC, yet I'm pretty sure they implement IDisposable.
 
B

Brian Gideon

The IDisposable interface is intended for the developer to be able to
control the life cycle of an object. That doesn't only mean to kill it
in a predictable way, but sometimes also to keep it alive in a
predictable way.

That was a very well thought out response.
 
H

Hilton

Agreed. Implementing IDisposable is a flag to the consumer, not the GC.
The GC doesn't know or care about IDisposable objects. If it did, then
you would have the issues currently surrounding Finalizers to content with
(and that's the exact reason it's recommended that you implement
IDisposable instead of using a Finalizer).

There's no way to "automate" this process without causing pain for those
of us who like performance or adding the requirement of multiple
collection cycles to release resources.

Sure there is. How would you call Dispose? You'd call it on an object -
right? That means that it would not be GC'd (yet) since you are holding a
reference to it, so everything works just fine as it always has. Now when
this object can be GC'd (no refs etc), then 'my' logic kicks in, disposes
the object and frees the memory ***IF*** it hasn't already been disposed.
It's just a safety net, not a new paradigm.

Your code is not affected, you can continue to optimize, but the GC will
dispose of any objects that need to be disposed, but weren't. Sounds good
to me.

Hilton
 
H

Hilton

Göran Andersson said:
The IDisposable interface is intended for the developer to be able to
control the life cycle of an object. That doesn't only mean to kill it in
a predictable way, but sometimes also to keep it alive in a predictable
way.

Just holding a reference to it will keep it alive as it always has.

Hilton
 
H

Hilton

Nicholas Paldino said:
Hilton,

This idea doesn't do much, really. It only serves to reward people for
not being aware of the implementation of their designs.

If you are not aware of the lifespans of the objects that you are
using, then that is an error, either in design, or implementation, or the
understanding of the underlying technologies and it should be fixed. If
something implements IDisposable, that should be a huge red flag that
tells the developer "hey, YOU (not the GC) need to pay extra attention to
me, as I am doing something that you want to pay attention to, and not
just leave lying around."

That's a great argument for using free/malloc instead of a GC. A GC is
there so that you don't have to worry about this stuff. All we've done is
reduce the set of objects we're watching from "all" to "some". I'm saying
that by adding a "if (!Disposed) o.Dispose()" would solve a lot of bug and
memory leaks - we see them here all the time. I see it in the CF too.

Hilton
 
G

Guest

But now the GC has to track every object that you've called Dispose on. And
how does it know what resources it holds? Should it keep track of all
object held within some class that called Dispose? What if those objects
have a Dispose method? Should the GC call it that too? What if it's
already been called? Now we need to track that. How about it's internal
objects? Track them too? It gets real ugly real fast. The metadata the GC
would have to hold would be large and the time required to Collect would
lengthen substantially. It's a lot easier, cleaner and certainly faster to
have the one who should know what needs to be Disposed - the application -
handle it.

The GC already spends more time than I'd like doing stuff I can't control.
The last thing I need is it doing more.


--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Managed Code in an Embedded World
www.OpenNETCF.com
 
K

KWienhold

Hi,

I'm sure I'm simplifying things here, but how about if the GC did this to
objects that implement IDisposable:
1. Always Generation 1 (I think that is the correct name)
2. Get aggressive with them:
a. Nuke 'em on a GC.Collect call (or equivalent)
b. Call Dispose on the object.

Yes, I understand that the compiler and the GC doesn't know what IDisposable
is, but surely it is a worthwhile consideration? This garbabe/resource
collection is particularly important in the CF world.

Hilton

I have to agree with the other posters here, I don't think this should
be something the GC handles by itself.
However, if you want your own classes to exhibit a similar behavior,
you could implement a finalizer that calls Dispose and call
GC.SuppressFinalize(this) if Dispose is called manually.
That makes sure that Dispose does get called, even if its in a non-
deterministic way. I believe this method still causes a small overhead
for using a finalizer (even if its not used), but I still do it with
classes that implement IDisposable to make sure clean-up happens at
some point.

hth,
Kevin Wienhold
 
D

Doug Semler

KWienhold said:
I have to agree with the other posters here, I don't think this should
be something the GC handles by itself.
However, if you want your own classes to exhibit a similar behavior,
you could implement a finalizer that calls Dispose and call
GC.SuppressFinalize(this) if Dispose is called manually.
That makes sure that Dispose does get called, even if its in a non-
deterministic way. I believe this method still causes a small overhead
for using a finalizer (even if its not used), but I still do it with
classes that implement IDisposable to make sure clean-up happens at
some point.


Whoa, wait. Finalize should NEVER call Dispose to clean up managed
resources, since the maaged resource references may no longer exist!



--
Doug Semler, MCPD
a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh).
The answer is 42; DNRC o-
Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira
erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
 
J

Jon Skeet [C# MVP]

Hilton said:
That's a great argument for using free/malloc instead of a GC. A GC is
there so that you don't have to worry about this stuff.

No, a GC is there so that you don't have to worry about this stuff *for
memory resources*. Not for other resources.
All we've done is reduce the set of objects we're watching from "all" to
"some".

That's a pretty big improvement, IMO.
I'm saying that by adding a "if (!Disposed) o.Dispose()" would solve a
lot of bug and memory leaks - we see them here all the time.

No, it wouldn't. You'd still have race conditions - you'd just see them
*slightly* less often, making them harder to find and fix. Any
IDisposable which directly has a handle on an unmanaged resource should
have a finalizer which calls Dispose anyway.
 
P

Peter Duniho

Hilton said:
[...]
Your code is not affected, you can continue to optimize, but the GC will
dispose of any objects that need to be disposed, but weren't. Sounds good
to me.

I'm not sure I understand the point you're trying to make. How is what
you're suggesting different from the already-existing finalizer
paradigm? Other than the fact that the finalizer needs to explicitly be
written to call Dispose(), I mean.

Is that all it is? Or is there something different you're getting at?

Pete
 
P

Peter Duniho

Doug said:
[...]
Whoa, wait. Finalize should NEVER call Dispose to clean up managed
resources, since the maaged resource references may no longer exist!

I don't disagree. But I was just assuming that we were talking about
unmanaged resources here. After all, those are the ones that cause the
most trouble if not disposed properly.

Did I miss something?

Pete
 
K

KWienhold

Whoa, wait. Finalize should NEVER call Dispose to clean up managed
resources, since the maaged resource references may no longer exist!

--
Doug Semler, MCPD
a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh).
The answer is 42; DNRC o-
Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira
erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?- Zitierten Text ausblenden -

- Zitierten Text anzeigen -

I was thinking of unmanaged resources, since those are normally the
ones that need to be cleaned up in the Dispose.
The GC handles cleaning up of managed resources just fine as far as I
know, so I don't really understand why one would even use IDisposable
on a class containing only managed resources.

Kevin Wienhold
 
P

Peter Duniho

KWienhold said:
I was thinking of unmanaged resources, since those are normally the
ones that need to be cleaned up in the Dispose.

Me too. :)
The GC handles cleaning up of managed resources just fine as far as I
know, so I don't really understand why one would even use IDisposable
on a class containing only managed resources.

I suppose one reason might be if you had a class that you wanted to keep
a reference to, but you were only interested in some post-processing
state and wanted to go ahead and release whatever managed resources were
used to get to that state.

I can't think of a class off the top of my head that uses Dispose() in
that way, but it wouldn't surprise me if it exists.

But this isn't a case where you need the GC to do the Dispose() for you.
It's more an example of explicitly controlling the lifetime of resources.

Pete
 
K

KWienhold

I suppose one reason might be if you had a class that you wanted to keep
a reference to, but you were only interested in some post-processing
state and wanted to go ahead and release whatever managed resources were
used to get to that state.

I can't think of a class off the top of my head that uses Dispose() in
that way, but it wouldn't surprise me if it exists.

But this isn't a case where you need the GC to do the Dispose() for you.
It's more an example of explicitly controlling the lifetime of resources.

Pete

That might be a reason, but in my mind it would violate the intent of
IDisposable. Maybe I'm nitpicking here, but if I saw someone call
Dispose on an instance and then use that instance afterwards I'd be
seriously confused.
Disposing something tells me that the instance is left in an unknown
state and shouldn't be used.
I'd probably use some another, properly named method to provide this
kind of cleanup.

Kevin Wienhold
 
J

Jon Skeet [C# MVP]

KWienhold said:
That might be a reason, but in my mind it would violate the intent of
IDisposable. Maybe I'm nitpicking here, but if I saw someone call
Dispose on an instance and then use that instance afterwards I'd be
seriously confused.
Disposing something tells me that the instance is left in an unknown
state and shouldn't be used.

Not necessarily. From the docs for IDisposable:

<quote>
Use this method to close or release unmanaged resources such as files,
streams, and handles held by an instance of the class that implements
this interface. This method is, by convention, used for all tasks
associated with freeing resources held by an object, or preparing an
object for reuse.
</quote>

Note the "or preparing an object for reuse". I can't think of any
examples where that actually *is* the use of IDisposable, but it would
be legal according to the docs.
 
L

Laura T.

Jon Skeet said:
Not necessarily. From the docs for IDisposable:

<quote>
Use this method to close or release unmanaged resources such as files,
streams, and handles held by an instance of the class that implements
this interface. This method is, by convention, used for all tasks
associated with freeing resources held by an object, or preparing an
object for reuse.
</quote>

Note the "or preparing an object for reuse". I can't think of any
examples where that actually *is* the use of IDisposable, but it would
be legal according to the docs.

Object pooling perhaps?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top