I’m running into a situation where I need the atomic sum of two values in memory. The code I inherited goes like this:
int a = *MemoryLocationOne; memory_fence(); int b = *MemoryLocationTwo; return (a + b) == 0;
The individual reads of a and b are atomic, and all writes elsewhere in the code to these two memory locations are also lockless atomic. However the problem is that the values of the two locations can and do change between the two reads.
So how do I make this operation atomic? I know all about CAS, but it tends to only involve making read-modify-write operations atomic and that’s not quite what I want to do here.
Is there a way to do it, or is the best option to refactor the code so that I only need to check one value?
Edit: Thanks, I didn’t mention that I wanted to do this locklessly in the first revision, but some people picked up on it after my second revision. I know no one believes people when they say things like this, but I can’t use locks practically. I’d have to emulate a mutex with atomics and that’d be more work than refactoring the code to keep track of one value instead of two.
For now my method of investigation involves taking advantage of the fact that the values are consecutive and grabbing them atomically with a 64 bit read, which I’m assured are atomic on my target platforms. If anyone has new ideas, please contribute! Thanks.
If you truly need to ensure that
aandbdon’t change while you are doing this test, then you need to use the same synchronization for all access toaandb. That’s your only choice. Each read and each write to either of these values needs to use the same memory fence, synchronizer, semaphore, timeslice lock, or whatever mechanism is used.With this, you can ensure that if you:
then
awill not change while you are readingb. But again, you have to use the same synchronization mechanism for all access toaand tob.To reflect a later edit to your question that you are looking for a lock-free method, well, it depends entirely on the processor you are using and on how long
aandbare and on whether or not these memory locations are consecutive and aligned properly.Assuming these are consecutive in memory and 32 bits each and that your processor has an atomic 64-bit read, then you can issue an atomic 64-bit read to read the two values in, parse the two values out of the 64-bit value, do the math and return what you want to return. Assuming you never need an atomic update to ‘
aandbat the same time’ but only atomic updates to ‘a‘ or to ‘b‘ in isolation, then this will do what you want without locks.