Interlocked vs volatile vs memory barriers

Hello,

interlocked vs volatile

I noticed Juce atomic operations used non volatile variables as parameters. However I checked and OSX and Win32 native atomic operations require volatile variables.

Why does Juce cast these variables? Is this safe?

[code]class JUCE_API Atomic
{

static void decrement (int32& variable);

#if JUCE_MAC && (GNUC < 4 || (GNUC == 4 && GNUC_MINOR < 2)) // Older Mac builds using gcc4.1 or earlier…

inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 (static_cast <int32_t*> (&variable)); }

#elif JUCE_USE_INTRINSICS // Windows…

inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); }

[/code]

AFAIK, if non volatile variables are used, optimizations of the compilers can generate situations where a thread can access a copy of the variable on the stack instead of accessing the variable in memory.

interlocked vs memory barrier

Also, according to the OSAtomic.h documentation (http://developer.apple.com/mac/library/documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/index.html) atomic operations with memory barrier versions should be preferred on OSX to ensure that memory shared between threads is properly synchronized. Atomic operations without memory barriers are used in OSX Juce.

Has anyone tested these issues?

Thanks! -Mathieu

The Atomic class has actually been completely rewritten since the version that you’re quoting there. Not much point in discussing defunct code, but if you have any queries about the new version, let me know…

Arf - I was still on v1.50. However version 1.51 does not seem to address these issues either.

interlocked vs volatile

I noticed Juce atomic operations used non volatile variables as parameters. However native atomic operations require volatile variables.

Juce:

class JUCE_API Atomic { ... static void decrement (int32& variable);
OSX:

Win32:

Why does Juce cast these variables?

AFAIK, if non volatile variables are used, optimizations of the compilers can generate situations in which a thread can access a copy of the variable on the stack instead of accessing the variable in memory.

interlocked vs memory barrier

Also, according to the OSAtomic.h documentation (http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/OSAtomicDecrement32.3.html) atomic operations with memory barrier versions should be preferred on OSX to ensure that memory shared between threads is properly synchronized. Juce source code uses atomic operations without memory barriers (for instance OSAtomicDecrement32 instead of OSAtomicDecrement32Barrier).

Is this intentional?

Thanks! -Mathieu

You’re still quoting code that doesn’t exist, you know… The casts are there because the OS functions take types that aren’t quite the same as the source type, e.g. it casts an int to an int32_t.

I guess there are a couple of places where it should probably use the barrier version. But note that the OSX functions are only used for backwards-compatibility - on an up-to-date gcc version, it uses the gcc sync functions instead.

Well I was quoting v1.51 which is still accessible as a downloadable zip…

I finally downloaded juce_Atomic.h from the SourceForge Git and now have the Atomic class refactoring which was checked-in in May. For sure this code addresses both the volatile and the barrier issues. Thanks.

This refactoring makes v1.51 somewhat obsolete…

A last question: I’m not familiar with XCode and had not checked the GCC version I was compiling with. So I was using 4.0. Would it be possible to set the GCC version in the juce.xcodeproj you supply in the zip?

Thanks! -Mathieu

Not sure I understand… Why wouldn’t you want it to use the default version? (which will normally be 4.2)

Arf.

My XCode is not up to date. I am using using XCode 3.1.2. I just checked and see I can download more recent versions (I thought I would get upgrade notifications like with other apps on OSX).

This is it! Thx.