|
|
|
Reference Count ImplementationReference counted objects must be allocated on the heap via operator new. In order to enforce this, all reference counted classes have a protected destructor. A reference counted object is created with a reference count of 1 and a floating flag set to true. calls to ref() will increment the reference count, calls to unref() will decrement the reference count. Additionally, there is a function ref_sink() to "consume" the floating state, it essentially does:
void
ref_sink()
{
ref();
if (floating)
{
floating = false;
unref();
}
}
In unref(), if the reference count drops to 0, the object will be destroyed via the delete operator. A warning may be issued if the object is still floating at this point, depending on whether the project policy allows unref (new Ref-Countable) semantics without ever sinking the object. ref() should refuse to operate on objects with a ref_count < 1 to catch after-delete reference counting operations where possible. Threading ConsiderationsThe reference counting primitives can be made atomic or thread-safe in terms of compare-and-swap with code like:
ref(): do tmp = ref_count;
while (!compare_and_swap(&ref_count, tmp, tmp + 1));
unref(): do tmp = ref_count;
while (!compare_and_swap(&ref_count, tmp, tmp - 1));
if (tmp == 1) /* destruction follows */;
ref_sink(): ref(); /* ref_count now >= 1 + (floating != false) */
do tmp = ref_count;
while ((tmp & FLOATING_BIT) &&
!compare_and_swap(&ref_count, tmp, tmp - (FLOATING_BIT + 1)));
/* ref_count now >= 1 */
It is desirable to use a very high bit for FLOATING_BIT, like 2147483648 to avoid early overflow in the above logic. |
|