Welcome back.

This week, a bit of pause after the series of posts on chapter 2 of my book. The content of this post is from appendix A, and it features the Handle class. As usual, I’ll be grateful for your feedback.

Next time, I’ll start a new series of posts on content that I haven’t published before: chapter 5, covering parameterized models and calibration. My plot for making myself write more seems to be working.

In other news, QuantLib 1.3 was released last week; here’s the list of changes. About a month ago I wrote on this blog that it would take me another couple of weeks to release it. Some people never learn… If you haven’t downloaded it yet, go get it.

Follow me on Twitter if you want to be notified of new posts, or add me to your circles, or subscribe via RSS: the buttons for that are in the footer. Also, make sure to check my Training page; you might be still in time for the next course.

Odds and ends: smart pointers and handles

The use of run-time polymorphism dictates that many, if not most, objects be allocated on the heap. This raises the problem of memory management—a problem solved in other languages by built-in garbage collection, but left in C++ to the care of the developer.

I will not dwell on the many issues in memory management, especially since they are now mostly a thing of the past. The difficulty of the task (especially in the presence of exceptions) was enough to discourage manual management; therefore, ways were found to automate the process.

The weapons of choice in the C++ community came to be smart pointers: classes that act like built-in pointers but that can take care of the survival of the pointed objects while they are still needed and of their destruction when this is no longer the case. Several implementations of such classes exist which use different techniques; we chose the smart pointers from the Boost libraries [1] (most notably shared_ptr, now included in the ANSI/ISO C++ standard [2]). You can browse the Boost site for documentation; here, I’ll just mention that their use in QuantLib completely automated memory management. Objects are dynamically allocated all over the place; however, there is not one single delete statement in all the tens of thousands of lines of which the library consists.

Pointers to pointers (if you need a quick refresher, see the aside at the bottom of the post for their purpose and semantics) were also replaced by smart equivalents. We chose not to just use smart pointers to smart pointers; on the one hand, because having to write

    boost::shared_ptr<boost::shared_ptr<YieldTermStructure> >

gets tiresome very quickly—even in Emacs; on the other hand, because the inner shared_ptr would have to be allocated dynamically, which just didn’t felt right; and on the gripping hand, because it would make it difficult to implement observability. Instead, a class template called Handle was provided for this purpose. Its implementation, shown in the listing below, relies on an intermediate inner class called Link which stores a smart pointer. In turn, the Handle class stores a smart pointer to a Link instance, decorated with methods that make it easier to use it. The desired behavior is obtained almost for free; since all copies of a given handle share the same link, they are all given access to the new pointee when any one of them is linked to a new object.

Listing: Outline of the Handle class template.

    template <class Type>
    class Handle {
      protected:
        class Link : public Observable, public Observer {
          public:
            explicit Link(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
            void linkTo(const shared_ptr<Type>&);
            bool empty() const;
            void update() { notifyObservers(); }
          private:
            shared_ptr<Type> h_;
        };
        boost::shared_ptr<Link<Type> > link_;
      public:
        explicit Handle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        const shared_ptr<Type>& operator->() const;
        const shared_ptr<Type>& operator*() const;
        bool empty() const;
        operator boost::shared_ptr<Observable>() const;
    };

    template <class Type>
    class RelinkableHandle : public Handle<Type> {
      public:
        explicit RelinkableHandle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        void linkTo(const boost::shared_ptr<Type>&);
    };

The contained shared_ptr<Link> also gives the handle the means to be observed by other classes. The Link class is both an observer and an observable; it receives notifications from its pointee and forwards them to its own observers, as well as sending its own notification each time it is made to point to a different pointee. Handles take advantage of this behavior by defining an automatic conversion to shared_ptr<Observable> which simply returns the contained link. Thus, the statement

    registerWith(h);

is legal and works as expected; the registered observer will receive notifications from both the link and (indirectly) the pointed object.

You might have noted that the means of relinking a handle (i.e., to have all its copies point to a different object) were not given to the Handle class itself, but to a derived RelinkableHandle class. The rationale for this is to provide control over which handle can be used for relinking—and especially over which handle can’t. In the typical use case, a Handle instance will be instantiated (say, to store a yield curve) and passed to a number of instruments, pricing engines, or other objects that will store a copy of the handle and use it when needed. The point is that an object (or client code getting hold of the handle, if the object exposes it via an inspector) must not be allowed to relink the handle it stores, whatever the reason; doing so would affect a number of other object (this is not as far-fetched as it might seem; we’ve been bitten by it). The link should only be changed from the original handle—the master handle, if you like.

Given the frailty of human beings, we wanted this to be enforced by the compiler. Making the linkTo method a const one and returning const handles from our inspectors wouldn’t work; client code could simply make a copy to obtain a non-const handle. Therefore, we removed linkTo from the Handle interface and added it to a derived class. The type system works nicely to our advantage. On the one hand, we can instantiate the master handle as a RelinkableHandle and pass it to any object expecting a Handle; automatic conversion from derived to base class will occur, leaving the object with a sliced but fully functional handle. On the other hand, when a copy of a Handle instance is returned from an inspector, there’s no way to downcast it to RelinkableHandle.

Bibliography

[1] Boost C++ libraries, http://www.boost.org.
[2] International Standards Organization, Programming Languages — C++, International Standard ISO/IEC 14882:2011.

Aside: pointer semantics

Storing a copy of a pointer in a class instance gives the holder access to the present value of the pointee, as in the following code:

    class Foo {
        int* p;
      public:
        Foo(int* p) : p(p) {}
        int value() { return *p; }
    };

    int i=42;
    int *p = &i;
    Foo f(p);
    cout << f.value(); // will print 42
    i++;
    cout << f.value(); // will print 43

However, the stored pointer (which is a copy of the original one) is not modified when the external one is.

    int i=42, j=0;
    int *p = &i;
    Foo f(p);
    cout << f.value(); // will print 42
    p = &j;
    cout << f.value(); // will still print 42

As usual, the solution is to add another level of indirection. Modifying Foo so that it stores a pointer to pointer gives the class both possibilities.

    int i=42, j=0;
    int *p = &i;
    int **pp = &p;
    Foo f(pp);
    cout << f.value(); // will print 42
    i++;
    cout << f.value(); // will print 43
    p = &j;
    cout << f.value(); // will print 0