Synchronized Smart Pointers

From SynchronizationStrategies:

Managing resources between threads is a thorny issue best left to garbage collectors. However, in CeePlusPlus, garbage collection is an even thornier issue. (But see GarbageCollectionInCpp, it might not be as thorny as you think!) The closest one can usually get is to use smart pointers.

SmartPointers are very useful. They make an instance own itself instead of forcing a housekeeper object to own it. If ownership is contentious, say if an object is being passed around frequently, it becomes extremely difficult to maintain control over that object. More so in a multithreaded application because the maintenance must be synchronized.

Therefore, use a smart pointer whose reference semantics (e.g. a reference counter) are synchronized. The smart pointer does all the maintenance work for you in one location in the code and in one location during runtime.

But, it should be noted that smart pointers are tricky. They don't handle circular references or self-references well. As much as they attempt to look like normal "dumb pointers," they aren't.

Another but, ReferenceCounting is inefficient compared to state-of-the-art garbage collectors, especially when paging behaviour is taken into account. Moreover, I gather from the above description that this "synchronized" smart pointer actually has to do a locking operation every time the refcount gets changed. This might give you so much lock contention as to lose all performance advantages of multithreading in the first place. That's why PythonLanguage has its global interpreter lock; an extreme form of CoarseGrainLocking.

A "synchronized" smart pointer does not have do a locking operation every time the refcount gets changed if the hardware has an atomic increment instruction. Most hardware does.

Unfortunately, ReferenceCounting is one of those square wheels that get reinvented again and again. -- StephanHouben

I've battled with the use of SmartPointers? in C++ for a long time. ReferenceCounting is fine, but tends to fall apart as the software becomes bigger and more complex; typically, this is because of circular references.

Recently, I hit upon a convention that has been working quite well for me in a heavily threaded C++ application. Essentially, I have two types of SmartPointers?: an owner and a reference. The owner object is a typical C++ SmartPointer, and includes ReferenceCounting. The reference object, however, simply performs the bookkeeping to record the existence of itself (the owner object creates an internal bookkeeping object that is shared with the owner and it's references). The owner object asserts if any reference objects exist when it goes to delete the owned pointer.

What this has done is made object ownership much more explicit within the code. Problems are typically found quite quickly in unit tests. I no longer have problems with circular references. The trade-off is that object lifetimes may be a bit longer then they otherwise could be, but I'd rather have this than trying to deal with complex circular references... -- OliverSeiler

This sounds like the Weak Reference concept used by boost's Smart Pointer package

(See BoostSharedPtr)
CategoryConcurrencyPatterns CategoryGarbageCollection CategoryCpp

View edit of April 17, 2006 or FindPage with title or text search