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.
