Friday, April 1, 2016

Weak pointers for reference counted objects

OpendTect has used reference counting for more than ten years in the visualization and the earth model libraries. We are now taking this one step further and introducing a weak pointer for reference-counted objects. In order to do so, we had to change the way reference counted objects work. Previously, our reference-counted objects used a macro which implemented the necessary functions. That has now been replaced by inheritance:

class A : public RefCount::Referenced
{
protected:
             ~A();
};

The good thing is that apart from this, the API remains the same, so no changes are needed by classes using reference counted classes.

This change enables us to do two things:

  1. Use RefMan<A> as class variables with a forward declared A. Previously, the compiler required a full definition of the A variable. Hence we can include less files and get slimmer dependency trees:

    #include <refcount.h>
    class A; //Forward declaration of A

    class B
    {
    public:
                    B();
    private:
        RefMan<A>   a_;
    };
  2. Use weak pointers. Weak pointers point to objects as long as objects are alive, but become NULL when the object they point to goes out of scope:

    #include <refcount.h>

    class A;

    class B 
    {
    public:
                    B(A* a) : a_(a) {}    void        compute();
    private:
        WeakPtr<A>  a_;
    };

    The variable a_ will be a valid pointer to the instance of A as long as the instance is alive. When the instance goes out of scope, it will be set to NULL. If you actually want to use the pointer in a_, you have to retrieve it using the WeakPtr<A>::get() function:

    void B::compute()
    {
        RefMan<A> a = a_.get();
        //Instance is reffed if still alive

        if ( !a ) //Check if it is alive
             return;

        a->doSomething();
    } //a goes out of scope, and A instance is unreffed
All reference counting is threadsafe, as it is managed by atomic variables. The new functionality is available in our master branch. It can unfortunately not be ported to the stable branch due to ABI restrictions.

No comments:

Post a Comment