5

InterlockedCompareExchange in Windows, as well as __sync_val_compare_and_swap in gcc take pointers, and so I can pass in any address e.g. pointing into a shared memory block into those functions.

For non-x86 architectures, I might have to ensure memory alignment for correctness, and for x86 (and maybe others), I might want to ensure cache-line alignment for performance, although correctness should not be an issue (-> x86 LOCK prefix).

Trying to get rid of some platform-dependent stuff in my code (Windows VC++ vs. GCC), I took a look at C++11's atomic_compare_exchange_weak and friends. But they all work on a variable of type std::atomic<T>*.

Is there a way to use arbitrary pointers with C++11's atomic functions? It doesn't look like a simple cast to std::atomic is gonna solve this.

Community
  • 1
  • 1
Evgeniy Berezovsky
  • 18,571
  • 13
  • 82
  • 156
  • Have a look at [this article](http://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong). Basically, if you're not already using std::atomic or something *roughly* equivalent (like hand-coded assembly or volatile variables), your code is probably already theoretically incorrect (though it may compile properly in practice, there's no guarantee for future compiles). Still a valid question though (+1) -- what about cross-platform swaps on volatile pointers? – Cameron Jun 11 '13 at 06:21
  • @Cameron I'm currently using `Interlocked...` and `__sync_...`, depending on the platform. I'm not sure if are you trying to say that is not safe? I just want to migrate those to `std::atomic...` if possible, to get rid of the `#ifdef`s. – Evgeniy Berezovsky Jun 11 '13 at 06:49
  • Ah no, sorry. I didn't mean to come across as quite so criticising... (I shouldn't comment at this time of night, it's 3AM here.) I meant, std::atomic is guaranteed to be safe, whereas using something else is harder to get right -- such as with raw pointers there's the chance of weird compiler optimizations unless they're `volatile` raw pointers. Your question, of course, stands as is -- my comment is really just a tangential thought (that your question brought to my mind since you didn't mention volatile pointers but rather arbitrary ones) which is, in retrospect, completely irrelevant! – Cameron Jun 11 '13 at 07:08

1 Answers1

3

Short answer: they can't. This is necessary for portability of the language since C++ does not want to require that every platform to have lock-free support for a specific set of data sizes. Using std::atomic<T> makes it easy for the library to transparently provide lock-free atomicity for some Ts and use a lock for others.

On the bright side, replacing T with atomic<T> in your codebase provides documentation of exactly what objects are used for synchronization, and provides protection against accidental non-atomic access to those objects.

Long answer: reinterpret_cast<std::atomic<decltype(t)>&>(t).store(value) may actually work on some implementations during the right phase of the moon, but it's the purest evil.

Casey
  • 41,449
  • 7
  • 95
  • 125
  • The `reinterpret_cast` looks evil indeed - couldn't `std::atomic` even imply word / cache line alignment, depending on the platform and implementation? In that case it could totally mess up my self-managed memory region. I guess this means that self-managed memory, like shared memory, and `std::atomic` don't mix, meaning I'd have to fall back to platform-dependent code. – Evgeniy Berezovsky Jun 18 '13 at 06:06
  • Any alignment/padding requirements must be "built in" to the type - the standard says nothing about requiring special memory management for atomics. I haven't used atomics in shared memory, but I've given advice here to people who have. – Casey Jun 18 '13 at 08:23