Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

little tricks....

35 views
Skip to first unread message

Chris M. Thomasson

unread,
Dec 9, 2023, 1:27:25 AM12/9/23
to
Food for thought. We can atomically increment a reference count along
with obtaining a reference to an object in a single fetch-and-add. All
in pure C++11

Say we have some objects:

collectors[CN];


And a reference count, say, 32 bit words:

RC = 0xRRRRRRCC

Where R is reference count space, and C is an index into collectors...

So, to obtain a reference we can simply:

word = fetch_and_add(&RC, 0x100);

Now we have incremented the count and obtained an index into the
collectors in one shot without DWCAS. ;^)

I cannot remember if this trick for single word proxy collectors is
patented!

Chris M. Thomasson

unread,
Dec 9, 2023, 1:36:23 AM12/9/23
to
On 12/8/2023 10:27 PM, Chris M. Thomasson wrote:
> Food for thought. We can atomically increment a reference count along
> with obtaining a reference to an object in a single fetch-and-add. All
> in pure C++11
>
> Say we have some objects:
>
> collectors[CN];
>
>
> And a reference count, say, 32 bit words:
>
> RC = 0xRRRRRRCC
>
> Where R is reference count space, and C is an index into collectors...
>
> So, to obtain a reference we can simply:
>
> word = fetch_and_add(&RC, 0x100);

Fwiw, another trick is to increment by 0x200 and use the odd number
(0x300) for atomic quiescence detection. Proxy collectors sure beat the
heck out of rwlock when it comes down to the iteration of large
collections of nodes... Here is an example test unit in Relacy:

https://pastebin.com/raw/f71480694

If interested, take careful notice of the following functions:
________________
collector& acquire()
{
// increment the master count _and_ obtain current collector.
unsigned int current =
m_current.fetch_add(0x20U, std::memory_order_acquire);

// decode the collector index.
return m_collectors[current & 0xFU];
}

void release(collector& c)
{
// decrement the collector.
unsigned int count =
c.m_count.fetch_sub(0x20U, std::memory_order_release);

// check for the completion of the quiescence process.
if ((count & 0xFFFFFFF0U) == 0x30U)
{
// odd reference count and drop-to-zero condition detected!
prv_quiesce_complete(c);
}
}
________________
0 new messages