Most people believe that having an atomic reference counter makes them safe to use RefPtr
on multiple threads without any more synchronization. Opposite may be truth, though!
Imagine a simple code, using our commonly used helper classes, RefPtr<>
and an object Type
with ThreadSafeAutoRefCnt
reference counter and standard AddRef
and Release
implementations.
Sounds safe, but there is a glitch most people may not realize. See an example where one piece of code is doing this, no additional locks involved:
RefPtr<Type> local = mMemeber; // mMember is RefPtr<Type>, holding an object
And other piece of code then, on a different thread presumably:
mMember = new Type(); // mMember's value is rewritten with a new object
Usually, people believe this is perfectly safe. But it’s far from it.
Just break this to actual atomic operations and put the two threads side by side:
Thread 1
local.value = mMemeber.value; /* context switch */ . . . . . . local.value->AddRef();
Thread 2
. . Type* temporary = new Type(); temporary->AddRef(); Type* old = mMember.value; mMember.value = temporary; old->Release(); /* context switch */ .
Similar for clearing a member (or a global, when we are here) while some other thread may try to grab a reference to it:
RefPtr<Type> service = sService; if (!service) { return; // service being null is our 'after shutdown' flag }
And another thread doing, usually during shutdown:
sService = nullptr; // while sService was holding an object
And here what actually happens:
Thread 1
local.value = sService.value; /* context switch */ . . . . local.value->AddRef();
Thread 2
. . Type* old = sService.value; sService.value = nullptr; old->Release(); /* context switch */ .
And where is the problem? Clearly, if the Release()
call on the second thread is the last one on the object, the AddRef()
on the first thread will do its job on a dying or already dead object. The only correct way is to have both in and out assignments protected by a mutex or, ensure that there cannot be anyone trying to grab a reference from a globally accessed RefPtr
when it’s being finally released or just being re-assigned. The letter may not always be easy or even possible.
Anyway, if somebody has a suggestion how to solve this universally without using an additional lock, I would be really interested!
The post Illusion of atomic reference counting appeared first on mayhemer's blog.