Take a look at the code here:
https://pastebin.com/raw/p1E9WN5i
Well there is something stupid I did. The code still works for me, but
its still pissing me off. It involves negating an unsigned int.
Take a look at the following function:
_____________________
void prv_quiesce_begin()
{
// Try to begin the quiescence process.
if (! m_quiesce.exchange(true, std::memory_order_acquire))
{
// advance the current collector and grab the old one.
unsigned int old = m_current.load(std::memory_order_relaxed) &
0xFU;
old = m_current.exchange((old + 1) & 1, std::memory_order_acq_rel);
collector& c = m_collectors[old & 0xFU];
// decode reference count.
//unsigned int refs = old & 0xFFFFFFF0U; HOLY SHIT!!!
long refs = old & 0xFFFFFFF0U;
// verify reference count and previous collector index.
// RL_ASSERT(!(refs & 0x10U) && (old & 0xFU) == (&c -
m_collectors));
// increment and generate an odd reference count.
if (c.m_count.fetch_add(refs + 0x10U,
std::memory_order_release) == (unsigned int)-refs)
{
// odd reference count and drop-to-zero condition detected!
prv_quiesce_complete(c);
}
}
}
_____________________
Now, this makes me feel bad. I should have just wrote it the following
way to begin with... Adding UINT_MAX + 1 should negate the reference
count without any casts:
_____________________
void prv_quiesce_begin()
{
// Try to begin the quiescence process.
if (! m_quiesce.exchange(true, std::memory_order_acquire))
{
// advance the current collector and grab the old one.
unsigned int old = m_current.load(std::memory_order_relaxed) &
0xFU;
old = m_current.exchange((old + 1) & 1, std::memory_order_acq_rel);
collector& c = m_collectors[old & 0xFU];
// decode reference count.
unsigned int refs = old & 0xFFFFFFF0U;
// verify reference count and previous collector index.
// RL_ASSERT(!(refs & 0x10U) && (old & 0xFU) == (&c -
m_collectors));
// increment and generate an odd reference count.
if (c.m_count.fetch_add(refs + 0x10U,
std::memory_order_release) == refs + UINT_MAX + 1)
{
// odd reference count and drop-to-zero condition detected!
prv_quiesce_complete(c);
}
}
}
_____________________
Much better!
refs + UINT_MAX + 1 should equal -refs... ;^)