Boost logo

Boost :

From: Bill Wade (bill.wade_at_[hidden])
Date: 2000-08-31 16:25:39


> From: William Kempf [mailto:sirwillard_at_[hidden]]

> You aren't suggesting that exchange is not useful, however,
> are you? It's really the only portable way to read/write an atomic_t
> value. (I'm not distinguishing exchange() from get()/set() because
> they are equivalent functionality with different interface
> signatures.)

L-value exchange (i.e. swap) is very useful and usually not available in a
fast atomic-over-both-arguments form.

R-value exchange (Atomic get-old-value-and-set-new-value) is useful, but is
a different operation from get(), and I still don't see how to use it to
implement get().

In procedural terms:

   // atomically return old value and set new value
   int AtomicGetAndSet(int& lvalue, int new_value)
   {
     Lock(lvalue);
     int result = lvalue;
     lvalue = new_value;
     Unlock(lvalue);
     return result;
   }

To me an atomic read looks like

  int AtomicGet(int& lvalue)
  {
    Lock(lvalue);
    int result = lvalue;
    Unlock(lvalue);
    return result;
  }

I think (please correct me if I have this wrong) you're saying to rewrite
Get as

  int AtomicGet(int& lvalue)
  {
    return GetAndSet(lvalue, lvalue);
  }

But that doesn't work. If we expand the function call we see

  int AtomicGet(int& a)
  {
    // Note that the second argument to GetAndSet is passed by value.
Simulate
    // this by invoking copy constructor before locking.
    int temp = a;
oops:
    Lock(a);
    int result = a;
    a = temp;
    Unlock(a);
    return result;
  }

If another thread does something (say Increment(a)) while Get() is at the
"oops" label, then Get will
  return the incremented a (that is ok, we had no guarantee which a we would
get).
  and put a back to its pre-incremented value (most certainly not ok for a
read).

In Win32 GetAndSet is named InterlockedExchange. The version of Get() that
works is a normal aligned 32-bit read (I sleep better if I make it a
volatile read).

Of course on Win32 you can write a working Get like this
  int AtomicGet(int& a)
  {
    int result = 0;
    InterlockedExchange(result, a);
    return result;
  }
But in this case the only thing InterlockedExchange did for you was to lock
result. To work it still needs integer copy construction to be atomic.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk