gnustep-dev
[Top][All Lists]
Advanced

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

Re: Unresolved Issues with libxml2


From: Fred Kiefer
Subject: Re: Unresolved Issues with libxml2
Date: Sun, 4 Mar 2012 10:28:21 +0100

Thank you Doug for your comprehensiv reply. I now understand the reasoning 
behind the old code a lot better. Being able to manipulate multiple trees of 
nodes without thinking about ownership and everything just works sounds very 
attractiv. There are a few reasons for GNUstep not to follow this line. The 
main one being of course that any deviation from Cocoa will result in loads of 
bug reports. Even the old test code children.m failed for GNUstep, a fact only 
hidden by the file catching the exception. Another problem is that the retain 
and release methods are now deprecated and we would need separate solutions for 
garbage collection and ARC. 

At the moment I would not suggest your "whole tree integrity" flag, as this 
increases the complexity of our code. Perhaps a private subclass, that could be 
used on Cocoa and GNUstep, would be an option? For now I would prefer to clean 
up and complete the current code. In a next step I would like to unify the 
NSXML classes with the GSXML ones and only after that extensions like yours 
seem like an interesting option.

I already started with the removal of the retain/release code, but forgot to 
add the autorelease call I wrote about in my previous mail. It would be great, 
if you find the time to test this code. And it would be even better, if you 
could provide more test code. I started off with a few more tests on Cocoa and 
I was really surprised by what I found there. Who would have thought that an 
NSXMLElement without name isn't equal to itself?

Fred

On the road

Am 03.03.2012 um 20:00 schrieb Doug Simons <address@hidden>:

> 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
>> 
> 



reply via email to

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