Boost logo

Boost :

From: Hamish Mackenzie (hamish_at_[hidden])
Date: 2003-06-25 07:14:52


On Wed, 2003-06-25 at 01:12, Stefan Seefeld wrote:
> hi there,
>
> some weeks ago I proposed an API for XML, which triggered an interesting
> discussion. Hamish Mackenzie proposed a somewhat simpler mechanism to attach
> the C++ wrapper objects to the C structs from libxml2.
>
> I reworked the API to use that mechanism, so now using an xml document
> looks somewhat like:
>
> dom::document_ptr document("1.0");
> dom::element_ptr root = document.create_root_node("root");
> dom::element_ptr child = root.append_child("child");
> dom::text_ptr text = root.append_text("hello world");
> for (dom::element_ptr::child_iterator i = root.begin_children();
> i != root.end_children();
> ++i)
> std::cout << i->get_name() << std::endl;
>
> As the wrapper objects have reference semantics, I append '_ptr' to
> their name to stress that fact. A practical side-effect of this is
> that the document is now ref-counted, as it doesn't own the node-wrappers
> any more (as was the case in my former API).

Why should the node-wrappers keep the document alive?

Here is the analogy I think works best...

container --> document
container::value_type --> node
container::iterator --> node_iterator
container::pointer_type --> node_pointer
container::reference_type --> node_reference

Consider the following....

std::vector< foo > x;
...
foo * y = &x[0];
x.erase( x.begin(), x.end() );

I don't expect y to add_ref x. I wouldn't mind if it did, but it
wouldn't make y any more valid after the call to erase.

So the problem with add reffing the document is... what happens if the
root node or some parent of a node you have a pointer to is erased from
the document? libxml2 has no way of knowing you have a pointer to a
child node.

I think the solution is that the node iterators/pointers/reference
should not own anything (as is the convention with containers). The
document owns the root node, the root node owns it's children and so on.

If a particular implementation (such as MSXML) has ref counting built in
that's fine but it should not be a requirement. The boost::xml
interface requirements could simply state "iterators, pointers and
references for nodes are invalidated by deleting the document to which
they belong or by erasing them from the document (erasing a parent node
erases it's children)". It doesn't matter if for some implementations
they are still valid. We can add a remove function something like...

class document
{
public:
  std::auto_ptr< document > remove( node_iterator i );
};

This would take a node and all its children and put them in a new
document object. An implementation that has a underlying mechanism for
nodes to exist without the implementations document object could allow
xml::document to exist with just a root node and make the appropriate
optimisation to remove.

-- 
Hamish Mackenzie <hamish_at_[hidden]>

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk