Re: Is Dipose( ) a contractual obligation, if you provide one?



Kevin Frey wrote:
If you have a class that manages a resource (or something similar
such as an unmanaged pointer), and you implement a Dispose( ) method,
are you mandating to the users of your assembly that they *must* use
this method to clean up (or endure leaks or whatever)? Does this
become one of their contractual obligations in using this assembly?

You're at least saying "it'd be a really good idea for you to call Dispose
on this object when you're done with it, or something expensive is likely to
be wasted."

Are are you simply saying to developers: "Because this class manages a
resource, Dispose( ) gives you the opportunity to force this object to
relinquish its resources at an explicit point." In other words, if
the user *does not* call Dispose( ), then the finaliser should still (at
some
point) take care of cleaning up the resources, and it is *legal* for
a program to be written this way?

Yes it's legal (if unadvisable), and the finalizer should take care. The
preferred pattern for implenting IDisposable is this (C# syntax, sorry):

class C : IDisposable
{
private void IDisposable.Dispose()
{
Dispose(true);
}

~C()
{
Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// release managed resources
GC.SuppressFinalize(this);
}

// release unmanaged resources
}
}


The reason I ask is that we have a quite complicated framework of
Managed objects (actually written in Managed C++) that control
unmanaged resources (native C++ objects). The key complication is
that there are dependencies amongst the unmanaged resources.

For example, a UEntity unmanaged object requires a USession unmanaged
object in order to communicate with an application server over
TCP/IP,. The UEntity unmanaged object is controlled by a managed
Entity object, and the USession object is controlled by a managed
Session object. Naturally enough when Entity finalises, it will
release its corresponding resources, with same said for the Session
object.
The nett result is that, without convoluted handling code, it is
entirely possible for Session to finalise *before* Entity. The
finaliser for Session would in turn clean up USession.

The finaliser for Entity is now stuck between a rock and a hard
place. It needs USession to ensure it can communicate something back
to the application server, yet USession has been destroyed.

It's important that the finalizer for Entity not try to do anything other
than clean up resources. That probably includes attempting to communicate.
If you have a "close" protocol, let Dispose() initiate that, but just drop
the connection if you get to the finalizer.

Has anyone come across this kind of situation before? It would seem
to me that the only practical way of ensuring that the dependencies
are retained is to use reference-counted pointers for the unmanaged
resources.
That way Session holds 1 reference to the USession object, and Entity
holds 1 reference. USession only "self-destructs" if the reference
count drops to zero, so a finalise of Session ahead of USession would
reduce the reference count but not result in object destruction of
USession because Entity is still holding a reference.

If anyone has solved this in any other different/lateral/imaginative
way I'd be pleased to hear about it.

You may indeed need to use reference counting on the unmanaged objects if
your UEntity has a direct relationship with a USession that's managed by a
different object, just as you would in a pure unmanaged case if a single
object (USession) has two "owners".

-cd


.



Relevant Pages

  • Re: " //Clean Up managed resources " f&*ck
    ... The finalizer is called by the GC. ... time (such as releasing internal unmanaged resources). ... Since Dispose ... it is about 'managed resource'. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Question on implementing IDisposable
    ... have dealth with the unmanaged resources and before you take your ... This class does not implement a finalizer ... The overloaded Dispose which takes a bool argument should be made ... Then, the base class can implement IDispose, so ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: How much do you leave to VB.Net GARBAGE COLLECTION???
    ... as necessary due to the Garbage Collection capability. ... those that implement IDisposable and have a Dispose method. ... From the Finalizer, ... asynchronously and unmanaged resources might not be freed in a timely ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How much do you leave to VB.Net GARBAGE COLLECTION???
    ... as necessary due to the Garbage Collection capability. ... those that implement IDisposable and have a Dispose method. ... From the Finalizer, ... asynchronously and unmanaged resources might not be freed in a timely ...
    (microsoft.public.dotnet.languages.vb)
  • Re: " //Clean Up managed resources " f&*ck
    ... The finalizer is called by the GC. ... time (such as releasing internal unmanaged resources). ... Since Dispose ... managed code is computer ...
    (microsoft.public.dotnet.languages.csharp)

Loading