Tracking Down a Problem I Already Solved

bug.gif

I hate being dense. Really. In the recent past, I realized that I can't really use the compare-and-swap in a multi-threaded environment like this:

  Node  *old = __sync_val_compare_and_swap(&mTail,
                                           mTail,
                                           newbie);

because it's possible that between the marshaling for the args, another thread would get in there and change the value of mTail so that this atomic operation would fail, but the returned value would not be what I expected it to be. It would be the previous value, but the new value would not be newbie, which is what I wanted.

What I was looking for was simply an exchange - I don't care about the current value, I just want to swap what's there now for something new, and give me the old while I give you the new.

No such luck. There's nothing like that in GCC.

So I'm back to the only thing I can do:

  Node   *t = mTail;
  while (!__sync_bool_compare_and_swap(&mTail, t, newbie)) {
    t = mTail;
  }

and in this we are forced to loop and get a consistent set, but in the end it's still just a swap. Sure do with they had one of those.

Anyway, I'm miffed at myself for spending several hours on this when I'd already solved it. The wrinkle came in the multi-threaded usage of the LinkedFIFO, and while my test cases worked, I didn't really check that there was no corruption in the data. I added those tests to the app and all of a sudden it was clear I had an issue. It took me about 5 mins to fix, and all was well, but finding the problem was hours.

Sometimes, I'm my own worst enemy. However, I will say that I'm getting far more comfortable with all this stuff the more I use it. Guess there's a silver lining in this after all.