In spite of the DF Police, I love the idea of providing and enforcing
disposable object ownership rules. However, what you're proposing (even
as supported by a language directly) has a syntax so heavy-duty as to be
prohibitive, both to understand and to use. Having said that, I don't
have anything better...

Chris Sells
http://www.sellsbrothers.com
http://www.develop.com

> -----Original Message-----
> From: Moderated discussion of advanced .NET topics.
> [mailto:ADVANCED-DOTNET@;DISCUSS.DEVELOP.COM]On Behalf Of Phil Parker
> Sent: 05 November 2002 19:48
> To: [EMAIL PROTECTED]
> Subject: [ADVANCED-DOTNET] Enforcing IDisposable ownership rules -
> guarantee of deterministic finalism
>
>
> Hi all,  I was pondering on some of the issues re. garbage collection,
ref
> counting and deterministic finalization which have been posted here
and had
> an idea, so I though I'd post it here and see what people think.
>
> Note - this idea may well be way off base.  Anyway...
>
> It occurred to me that one of the main problems with IDisposable is
the
> lack of guarantee that finalization will take place as there is
virtually
> no way to even warn the programmer that they are misusing a class
derived
> from IDisposable - e.g. the programmer is not ensuring that a resource
is
> disposed within a try/finally block, a using clause or that in the
case of
> a class which stores a reference as a member variable that the class
itself
> implements IDisposable.
>
> Now, it occurred to me that one way of ensuring that a disposable
resource
> is disposed of correctly would be to enforce an ownership rule,
whereby a
> disposable resource MUST always have an assigned owner.
>
> This assigned owner could be a class instance, but could also be a
scope
> block, local function scope, or assembly scope.
>
> In my example, this would involve the specification of two interfaces
- one
> for a disposable resource class and one for a disposable resource
class
> owner.  See below.
>
> interface IDisposable {
>    void AssignOwner(IDisposableOwner owner);
>    void Dispose();
> }
>
> interface IDisposableOwner : IDisposable {
>    void AddResource(IDisposable resource);
>    void RemoveResource(IDisposable resource);
> }
>
> The implementation of the two interfaces would look something like the
> following examples:
>
> class MyResource : IDisposable
> {
>    IDisposableOwner m_owner = null;
>    File m_file = new File("c:\temp.file");
>
>    public void AssignOwner(IDisposableOwner owner)
>    {
>       if(m_owner != null) m_owner.RemoveResource(this);
>       owner.AddResource(this);
>       m_owner = owner;
>    }
>
>    public void Dispose()
>    {
>       m_file.close();
>
>       if(m_owner != null) m_owner.RemoveResource(this);
>    }
> }
>
> class MyResourceOwner : IDisposableOwner
> {
>    ArrayList m_resources = new ArrayList();
>    IDisposableOwner m_owner = null;
>
>    public void AddResource(IDisposable resource)
>    {
>       m_resources.Add(resource);
>    }
>
>    public void RemoveResource(IDisposable resource)
>    {
>       m_resources.Remove(resource);
>    }
>
>    public void AssignOwner(IDisposableOwner owner)
>    {
>       if(m_owner != null) m_owner.RemoveResource(this);
>       owner.AddResource(this);
>       m_owner = owner;
>    }
>
>    public void Dispose()
>    {
>       // dispose of each resource - this will result in a call to
>       // RemoveResource, so the size of our list should decrease by
>       // one for each call until we have no resources left.
>       while(m_resources.Count() > 0) m_resources[0].Dispose();
>    }
> }
>
> I know that the above code does not handle all contingencies such as
> multiple calls to dispose etc. but this is more for example.
>
> Note that most of the above code could be auto-generated by the
compiler so
> that the above code could probably be replaced with something like the
> following:
>
> [disposable()]
> class MyResource
> {
>    File m_file = new File("c:\temp.file");
>
>    void Dispose()
>    {
>       m_file.close();
>    }
> }
>
> [disposableowner()]
> class MyResourceOwner
> {
> }
>
> Now when instantiating a disposable class, the compiler would require
the
> specification of an owner.  The specification of the owner might be
> specified through a modified new operator for disposable resources,
e.g.
>
> new(owner) ClassName(parameters...)
>
> The new operator would behind the scenes call AssignOwner(owner) on
the
> created disposable class.
>
> We now also add some new keywords, which allow the use of scope to
define
> an instance of a scope class which implements IDisposableOwner and
handles
> release of resources owned by a scope.  The scope instance would be
> disposed of at the end of the code block which it encloses.
>
> This could look something like this:
>
> scope(scope name)
> {
> }
>
> We would have some predefined instances of scope also for local
function
> scope and for the assembly (in the case of assembly, when the assembly
is
> unloaded, it would release all disposable resources it owns).
>
> Some examples then of how this would look.  Note, this example would
make
> use of the previously defines MyResource class.
>
> [disposableowner()]
> class MyExample
> {
>    MyResource m_resource;
>
>    public MyExample()
>    {
>       // create an instance of the resource with ourselves as
>       // the owner
>       m_resource = new(this) MyResource();
>    }
>
>    public void Example1()
>    {
>       // create an instance local to the function, using the
predefined
>       // localscope instance (note compiler would only create instance
>       // if used).
>
>       MyResource inst_localToFunc = new(localscope) MyResource();
>
>       scope(myScope)
>       {
>          // create an instance local to this scope
>          MyResource inst_localToScope = new(myScope) MyResource();
>
>       }   // here Dispose is called on the myScope scope instance
>    }
>
>    public MyResource CreateResource(IDisposableOwner owner)
>    {
>       return new(owner) MyResource();
>    }
>
>    public void StoreResource(MyResource resource)
>    {
>       // assign ourself as the new owner of this resource
>       resource.AssignOwner(this);
>
>       // release the current resource if any
>       if(m_resource != null) m_resource.Dispose();
>
>       // assign reference to member variable for use later by this
class
>       m_resource = resource;
>    }
> }
>
> I can see a couple of things which this doesn't account for.  For
example,
> in StoreResource, the developer still needs to take care to dispose of
the
> current resource prior to assignment to m_resource.  If this was not
done,
> the resource would still be released upon disposal of the MyExample
> instance, but obviously it should be done earlier.
>
> So, any opinions on this ?  There are probably glaring errors, but I
> thought I'd post and see what anyone thinks.
>
>
> Phil

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to