gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Unresolved Issues with libxml2


From: Ivan Vučica
Subject: Re: Unresolved Issues with libxml2
Date: Sun, 4 Mar 2012 22:32:04 +0100

From what I understand, you want to access siblings by asking the parent about 
the sibling, even though the parent is destroyed?

That's as if a member of NSArray counted on the NSArray being kept around 
instead of keeping interesting objects around. If the parent is removed, child 
shouldn't count on it and that's it. If you need information on siblings, make 
sure the parent shares it with you appropriately.

Subclassing NSXMLElement and overriding +[NSXMLDocument 
replacementClassForClass:] (still nonfunctional in GNUstep) is a good way to 
make parent notify its children it is about to be destroyed and that they 
should keep the siblings around in another way. Or to prevent its destruction. 
Or something else.

I still think that if parent gets destroyed, children should count on 
possibility of that happening, or (even better) the code that performs 
destruction should count on possibility of that happening and prevent children 
from lingering around (i.e. releasing any references to children that are still 
around).

On 3. 3. 2012., at 20:00, Doug Simons <address@hidden> wrote:

> Hello Fred,
> 
> That's a very interesting idea -- and perhaps you've already implemented it 
> (I've been busy with some issues with releasing our software so wasn't able 
> to find the time to respond sooner). And if this is how Cocoa does it then 
> perhaps it is what GNUstep should do, but I'm not entirely happy with the 
> idea.
> 
> I don't entirely like it because I believe it creates the potential for some 
> rather odd and potentially unexpected (and undesirable) behavior, although 
> perhaps not all that likely in practice. But please indulge me for a moment, 
> if only so that I can justify to myself the rather considerable effort that I 
> put into making the current (possibly overly-complex) scheme work. ;-)
> 
> Imagine a scenario where an NSXMLDocument is created (by parsing an XML 
> document, let's say) and retained by an object that we'll call Ancestor. 
> Another object, Son, is created that references (and retains) one of the 
> NSXMLElements that is a descendant somewhere further down in the tree. 
> Ancestor and Son are used and accessed in various places in the application. 
> At any time, Son is able to access its Parent node, and from there can gain 
> access to any of Parent's other children -- Son's siblings. 
> 
> Now, at some point in time every object in the application with a direct 
> reference to Ancestor is released, causing Ancestor to be fully released and 
> (under the scheme you're proposing) deallocated. Suddenly and without 
> warning, through no action of its own, Son is detached and made an orphan, 
> with no parent, and no way to access its siblings even though some of them 
> may already be instantiated as Obj-C objects, which are now similarly 
> orphaned.
> 
> Perhaps that's not the most likely scenario, but I don't think it's entirely 
> far-fetched. The only solution I see for such a scenario is for the 
> application author to have Son keep and retain a reference to Ancestor for as 
> long as Son is around -- but then you've suddenly created exactly the kind of 
> retain loop between Son and Ancestor that the current NSXMLNode memory 
> management scheme goes to great lengths to resolve, so it will all "just 
> work" for the application developer.
> 
> Under the current scheme, as long as the application holds a retain on any 
> Obj-C object anywhere in the tree, the entire underlying tree structure and 
> any other Obj-C objects that have been instantiated as part of it are kept in 
> memory. When the final "external" (from outside of the tree) retain is 
> released, the entire structure and all of the objects are freed. A fair bit 
> of complexity internal to the framework to make using the framework simple.
> 
> So I'm disappointed to hear that Cocoa does it the cheap way! I appreciate 
> that that approach will be simpler to implement and easier to understand the 
> internal GNUstep code, but I wonder if it would be at all worthwhile at this 
> point to allow a "WholeTreeIntegrity" flag to enable a developer to choose 
> either memory behavior. Any thoughts?
> 
> Cheers,
> 
> Doug
> 
> On Mar 2, 2012, at 10:06 AM, Fred Kiefer wrote:
> 
>> On 01.03.2012 11:08, Richard Frith-Macdonald wrote:
>>> 
>>> Agreed.  In particular we need a lot of tests to run on Apple systems
>>> to find out exactly how their object ownership model works.  What
>>> happens when you create documents and then release them while holding
>>> references to various nodes within them?  Does behaviour vary
>>> depending on how documents are created?  What about standalone nodes
>>> without documents?  What about namespaces?!!
>> 
>> It turns out that things are a lot simpler than we thought. I wrote a few 
>> tests on Cocoa and nothing of that mysterious behaviour that we tried to 
>> mimic showed up. It looks like Apple implemented a simple top down approach. 
>> The parent retains the child and nothing more. And we had even test code 
>> that took advantage of that behaviour, see basic.m in NSXMLNode:
>> 
>>   NSXMLElement *node = [[NSXMLElement alloc] initWithKind: NSXMLElementKind];
>>   NSXMLDocument *docA = [[NSXMLDocument alloc] initWithRootElement: node];
>>   NSXMLDocument *docB = nil;
>>   // NSLog(@"Here...");
>>   [node detach];
>>   PASS(docB = [[NSXMLDocument alloc] initWithRootElement: node], "Detached 
>> children can be reattached.");
>>   [docA release];
>>   // NSLog(@"Here... again");
>>   [docB release]; <-- HERE
>>   docA = [[NSXMLDocument alloc] initWithRootElement: node];
>>   // NSLog(@"Yet again");
>>   PASS_EXCEPTION(docB = [[NSXMLDocument alloc] initWithRootElement: node], 
>> NSInternalInconsistencyException, "Reusing a child throws an exception");
>> 
>> Did you spot the release on the document docB? This make the node usable 
>> again, that is node no longer has a parent and may be used as a root element 
>> in docA. I added a few tests that prove this behaviour. After the release of 
>> docB parent of node is nil!
>> This could be implemented rather easily by detaching all subnodes of any 
>> deallocated node. The only clever bit needed here is to make sure we free up 
>> the libxml2 nodes that don't have corresponding Objective-C objects, but I 
>> think that will happen automatically if we free the libxml2 node after 
>> detaching all the subnodes. There may be a few cases where this behaviour is 
>> slightly slower, but it is a lot more consistent than the current code.
>> Any objections? Otherwise I go ahead and implement this.
>> 
>> 
>> _______________________________________________
>> Gnustep-dev mailing list
>> address@hidden
>> https://lists.gnu.org/mailman/listinfo/gnustep-dev
>> 
> 
> 
> _______________________________________________
> Gnustep-dev mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/gnustep-dev



reply via email to

[Prev in Thread] Current Thread [Next in Thread]