Making C++ like Python: The Anderson Smart Pointer Pattern

Choosing to use C++ brings the additional complexity of memory management.  Dennis Ritchie once stated: The C Programming Language — A language which combines the flexibility of assembly language with the power of assembly language. C++ inherits much of that _flexibility, _however, this incidental complexity, can be relegated to a single class, leaving you with the high-level elegance of Python. RAII help with this additional complexity, however without a pattern for guidance implementing RAII consistently can be difficult, defeating the safety it provides.

Resource Acquisition Is Initialization (RAII) is a powerful tool for managing resources.  RAII justifies the apparent missing finally clause. Stroustrup claims that with proper RAII,  finally is not required. D also implements RAII with scope operators. Ok, so RAII is powerful, but what is it?

In C++, destructors are the only entity guaranteed to execute after an exception.  So resources which need to be automatically reclaimed need  to acquire at initialization, and release at destruction.  Such resources must be declared on the stack, to permit this idiom.

Writing exception-safe code, e.g. managing resources throughout exceptions is difficult, and while RAII makes it easier, managing RAII correctly is difficult without a pattern. A colleague of mine, Anderson, developed a fantastic pattern/policy using smart pointers which makes RAII automatic.

Two patterns compose the Anderson Smart Pointer Pattern: Factory Constructor, and PIMPL.

#ifdef _WIN
#include <memory>
#else
#include <tr1/memory>
#endif

class Name
{
public:
#ifdef _WIN
    typedef std::shared_ptr Ptr; //This uses the class as a namespace.
    typedef std::weak_ptr WeakPtr;
#else
    typedef std::tr1::shared_ptr Ptr;
    typedef std::tr1::weak_ptr WeakPtr;
#endif
    static name::Ptr construct(); //Factory Constructor
    virtual ~name();
private:
    Name(); //Notice the constructor is private
    name::WeakPtr self; //self (from python), replaces this
};

Name::Ptr Name::construct()
{
    Name::Ptr c(new Name());
    //Self completes the PIMPL idiom,
    //thereby hiding all behavior behind a safe, reference counted wall
    c->self = c;
    return c;
}

This pattern is used as an RAII policy. Using the pattern liberally can eliminate new and delete from your program, and you will not leak memory. Even with multiple exceptions, you’re program will not leak.  Creating an instance of an RAII class is easy now:

Name::Ptr myInstance = Name::construct();

This Pattern will make one extra virtual call as it performs the reference counting, but the performance hit is typically nominal compared to the safety it provides to the system. The Anderson Smart-Pointer Pattern increases robustness of your programs, but interestingly it also provides a new elegance. Since one is not managing memory, and resources constantly, it makes C++ perform more like a high level language. For example, I implemented a red black tree using this pattern.  I didn’t need to worry about deleting nodes, just the requirements of my program. With the incidental complexity relegated to a single class, I am left with the elegant, expressiveness of Python, yet retain the raw performance of C++.

Tags// , , , , ,
comments powered by Disqus