This looks correct at a superficial glance, but every time you use two interlocked operations in a row you are exposing yourself to the ABA problem. In this case one thread fail to change it from 0xFFFF to 1 (the ICX returns !=0xFFFF
) so it goes ahead and takes the if
branch and increments it. Before it runs the InterlockedIncrement
another threads changes the m_ref
back to 0xFFFF and the original thread increments 0xFFFF. Depending on the type/semantics of m_ref the effect will wary, but will surely be bad.
You should do one single ICX operation, for both the 0xFFF to 1 and X to X+1, and always retry if you lost the ICX:
volatile <type> m_ref;
<type> ref, newRef, icxref;
do
{
ref = m_ref;
newRef = (0xFFFF == ref) ? 1 : ++ref;
icxref = InterlockedCompareExchange (&m_ref, newRef, ref);
} while (icxref != ref);
if (newRef == 1 && ref != 0xFFFF)
{
DoSomething ();
}