tags:

views:

327

answers:

3

I have googled for atomic increment and decrement operators on Mac OS X and found "OSAtomic.h", but it seems you can only use this in kernel space.

Jeremy Friesner pointed me at a cross-platform atomic counter in which they use assembly or mutex on OS X (as far as I understood the interleaving of ifdefs).

Isn't there something like InterlockedDecrement or atomic_dec() on OS X ?

+5  A: 

What makes you think OSAtomic is kernel space only? The following compiles and works fine.

#include <libkern/OSAtomic.h>
#include <stdio.h>

int main(int argc, char** argv) {
  int32_t foo = 1;
  OSAtomicDecrement32(&foo);
  printf("%d\n", foo);

  return 0;
}
wich
Geee, that's weird ! http://developer.apple.com/Mac/library/documentation/Darwin/Reference/KernelIOKitFramework/OSAtomic_h/index.html specifies OSDecrementAtomic, but I see no reference to OSAtomicDecrement32 even though it compiles fine. The kernel only thing was read on a mailing list archive... ThanksPS: If you know why the doc says differently from your code, I'd be glad to know.
Gaspard Bucher
The `libkern` part does not imply _kernel mode_. They are offered as part of the kernel and driver development framework - see (http://developer.apple.com/mac/library/documentation/DriversKernelHardware/Reference/libkern_ref/index.html) for details. You might want to use the `OSAtomicDecrement32Barrier()` variant instead though.
D.Shawley
@D.Shawley: I don't need the memory barrier since I'm not allocating memory (I use the counter for a concurrent reference counting class).
Gaspard Bucher
@Gaspard Bucher man is your friend ;) I just used `man atomic`
wich
@wich I've had locale issues with manpages (man pages not found) and got the habit to look at other sources (XCode, developer.apple.com). I'll try again.
Gaspard Bucher
@Gaspard Bucher simply typing man $topic in any web search engine will get you the manpage as well, you could even define an alias to do the search directly in a text web browser ;)
wich
I don't think memory barriers are related to allocating memory... rather, they prevent the processor from re-ordering load and store operations across the barrier. I'm not sure whether they are needed for reference-counting, but I suspect they are (assuming you want your code to run correctly on multiprocessor Macs). Perhaps someone more knowledgable than I can confirm that, though.
Jeremy Friesner
@Jeremy memory barriers are related to memory allocation: "For example, if you want to initialize a shared data structure and then atomically increment a variable to indicate that the initialization is complete, then you must use OSAtomicIncrement32Barrier() to ensure that the stores to your data structure complete before the atomic add." (man atomic). Appart from this, ALL atomic operations are "thread and multiprocessor safe".
Gaspard Bucher
@Gaspard, what you quoted doesn't mention memory allocation, only initialization. They are different things -- memory allocation involves requesting memory from the heap; initialization is just writing values into an already-allocated region of memory.
Jeremy Friesner
@Gaspard: no, memory barriers prevent the CPU and compiler from reordering memory accesses. And yes, you pretty much always need that. Otherwise you get an atomic increment, but no guarantee of *when* the variable is incremented relative to the rest of your program.
jalf
A: 

You could also check out Intel's Threaded Building Blocks for their atomic template class.

imaginaryboy
A: 

You can also use IncrementAtomic() and DecrementAtomic() via CoreServices:

#include <CoreServices/CoreServices.h>

int main(int argc, char** argv) 
{
  int val = 0;
  IncrementAtomic(&val);
  DecrementAtomic(&val);    

  return 0;
}

Note: the return value of these functions is the value of the integer before it is incremented, so if you want similar behavior to the Win32 InterlockedIncrement() and InterlockedDecrement() functions, you will need to create wrappers that +1 to the return value.

Kurt