Consider the following code:
//!
Since the underlying libxml2 structures are always shared, a reference count system is required to avoid things like:
//!
The only solution is to use a reference count; but the reference count must be stored in the wrapped structure. How wxXml2Wrapper handle this problem ? Well, all libxml2 structure has a VOID* field called "_private" which can be safely used by external functions to hold user contents. The GetPrivate() function casts that pointer to a reference to a integer so that it can be used as an int instead of a pointer to void.
With reference counting the destructor of a wxXml2Wrapper knows if it is the only instance of that structure (and in this case it should free the structure) or if other wxXml2Wrappers still own that structure (and in this case it only decreases the refcount):
//!
Anyway there is another thing to consider: libxml2 implements "recursive destruction". When a node is destroyed, all its children are too. This means that we must also be careful not to break libxml2 memory representation destroying a node's child when it's still linked to its parent. Precisely, when a node (but also a property, a dtd, a namespace...) is part of a wider XML tree, we must *never* delete the node when the relative wxXml2Wrapper is destroyed. This is why all wxXml2Wrappers must implement the IsUnlinked() function: the DestroyIfUnlinked() function uses it to find when nodes are unlinked from a wider tree and thus must be destroyed by xml2 wrapper. However, this rises another problem ! Consider the example below:
//!
How can we solve this problem ? One solution could be not only to check if the node is unlinked but also to check if all children refcounts are set to zero, in each node destructor. However, I did not implement this solution because it can make all wxxml2 wrappers very slow: wxXml2Nodes are continuosly created & destroyed. The solution I adopted is simply to force the user (you!) to call the wxXml2Wrapper::DestroyIfUnlinked() function in the right order. This approach is not more restrictive of the approach used, for example, by libxml++ which uses pointers and thus require the DELETE calls to be in the right order. The example above must thus be rewritten as:
//!