Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Redux: RAII adapter for Xerces

, 5 Aug 2010
Rate this:
Please Sign up or sign in to vote.
A shared_ptr memory manager for the Xerces XML parser

In my previous entry, C++ RAII adapter for Xerces, I presented a simple memory management wrapper for Xerces types. Because of the way Xerces manages memory, I said, the quite handy boost::shared_ptr couldn't be used, so I wrote the memory management code myself to produce a safe wrapper in the style of std::auto_ptr.

However, as Alf P. Steinbach pointed out, I was wrong, in that boost::shared_ptr could be used by taking advantage of the custom deleter facility offered by that class. One benefit is that I can get rid of my hand-rolled memory management, but on the other hand, I’ll have to adjust the public interface to reflect different semantics.

The custom deleter version of the boost::shared_ptr takes a deleter function as a constructor argument, and is perfectly happy with taking a static member function.

template
class shared_xerces_ptr
{
    // The actual data we're holding
    boost::shared_ptr item_;

    // Function to release Xerces data type with a release member function
    template
    static void do_release(T* item)
    {
        // Only release this if it has no owner
        if (0 == item->getOwnerDocument())
            item->release();
    }
    // Specializations for character types, released by XMLString::release
    template
    static void do_release(char* item)
    {
        XMLString::release(&item);
    }
    template
    static void do_release(XMLCh* item)
    {
        XMLString::release(&item);
    }
public:
...
    // Assignment constructor
    shared_xerces_ptr(T* item)
      : item_(item, do_release )
    {}
    // Release currently held data, if any, to hold another
    void assign(T* item)
    {
        item_.reset(item, xerces_deleter );
    }
...

Unlike my previous effort, the auto_xerces_ptr, there is no need here to write a custom destructor, as the boost::shared_ptr takes care of that. Neither do I need to hide the copy constructor or assignment operator, as the boost::shared_ptr makes those safe, too.

But by the same token, I can’t provide a xerces_release function to release the data, like I did in auto_xerces_ptr. Since the boost::shared_ptr is safe with multiple copies, I cannot guarantee when held data will be released; if there are multiple references to it, it will only be released when the last reference is gone. For the same reason, the auto_xerces_ptr::yield would make no sense in the shared_xerces_ptr class, simply because there might be other instances referencing the data. Instead, I’ll provide a reset function, and leave it at that.

The final difference is to make the assignment operator work like we're used to, and make it chainable.

template
class shared_xerces_ptr
{
    // The actual data we're holding
    boost::shared_ptr item_;

    // Function to release Xerces data type with a release member function
    template
    static void do_release(T* item)
    {
        // Only release this if it has no owner
        if (0 == item->getOwnerDocument())
            item->release();
    }
    // Specializations for character types, released by XMLString::release
    template
    static void do_release(char* item)
    {
        XMLString::release(&item);
    }
    template
    static void do_release(XMLCh* item)
    {
        XMLString::release(&item);
    }
public:
    // Default constructor
    shared_xerces_ptr()
    {}
    // Assignment constructor
    shared_xerces_ptr(T* item)
      : item_(item, do_release )
    {}
    // Assignment of data to guard
    shared_xerces_ptr& operator=(T* item)
    {
        assign(item);
        return *this;
    }
    // Give up hold on data
    void reset()
    {
        item_.reset();
    }
    // Release currently held data, if any, to hold another
    void assign(T* item)
    {
        item_.reset(item, do_release );
    }
    // Get pointer to the currently held data, if any
    T* get()
    {
        return item_.get();
    }
    const T* get() const
    {
        return item_.get();
    }
    // Return true if no data is held
    bool is_released() const
    {
        return (0 == item_.get());
    }
};

There you have it. Not a replacement for auto_xerces_ptr, but a complement. Again, if you find it useful, or have suggestions for improvements, please let me know.


Tagged: C++, template, Xerces, XML

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

Orjan Westin

United Kingdom United Kingdom
Orjan has worked as a professional developer - in Sweden and England - since 1993, using a wide range of languages (C++, Pascal, Delphi, C, C#, Visual Basic, PHP, Python and x86 assembler), but tends to return to C++.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 5 Aug 2010
Article Copyright 2010 by Orjan Westin
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid