What is the replacement for OSAtomicCompareAndSwap32Barrier?

I am converting the example code in Learning CoreAudio by Adamson & Avila to Swift. In one of the examples, they use Apple's CARingBuffer C++ code. In trying to get that working, I get a warning:

OSAtomicCompareAndSwap32Barrier' is deprecated: first deprecated in macOS 10.12 - Use std::atomic_compare_exchange_strong() from <atomic> instead

I'm not familiar with C++ and I'm having trouble figuring out how to use atomic_compare_exchange_strong(). I've also had trouble figuring out what OSAtomicCompareAndSwap32Barrier is supposed to do.

The only place it is called in CARingBuffer is

void	CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime)
{
	UInt32 nextPtr = mTimeBoundsQueuePtr + 1;
	UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask;
	mTimeBoundsQueue[index].mStartTime = startTime;
	mTimeBoundsQueue[index].mEndTime = endTime;
	mTimeBoundsQueue[index].mUpdateCounter = nextPtr;
  CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);
}

The call to CAAtomicCompareAndSwap32Barrier directly calls OSAtomicCompareAndSwap32Barrier.

Even with the deprecation warning, the code performs as expected, but I'd like to eliminate the warning.

Answered by MarkErbaugh in 709341022

In this case, I found an answer. My C++ is rusty, but this works.

The purpose of the call was to increment a pointer (mTimeBoundsQueuePtr) in a thread-safe manner.

In CARingBuffer.h, at the top of the file, I added

#include <atomic>

and changed the declaration of mTimeBoundsQueuePtr at the bottom from

UInt32 mTimeBoundsQueuePtr;

to

std::atomic<UInt32> mTimeBoundsQueuePtr;

Then in CARingBuffer.cpp, I changed the last line of CARingBuffer::SetTimeBounds

from

CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);

to

mTimeBoundsQueuePtr++; 

This is a c++ method of the atomic includes. You will have to probably implement an Objective/C++ wrapper around the method & then export it to swift via bridging file:

atomic: references https://www.cplusplus.com/reference/atomic/atomic/

Thanks for the reply, but I'm still not clear. The atomic reference shows a function that take 4 parameters and returns a bool. The CAAtomicCompareAndSwap32Barrier takes 3 parameters and doesn't return a value. How do I map the CAAtomic parameters to the atomic parameters?

Can someone explain what the parameters to CAAtomic... are and what the function does to them?

Thanks, Mark

Accepted Answer

In this case, I found an answer. My C++ is rusty, but this works.

The purpose of the call was to increment a pointer (mTimeBoundsQueuePtr) in a thread-safe manner.

In CARingBuffer.h, at the top of the file, I added

#include <atomic>

and changed the declaration of mTimeBoundsQueuePtr at the bottom from

UInt32 mTimeBoundsQueuePtr;

to

std::atomic<UInt32> mTimeBoundsQueuePtr;

Then in CARingBuffer.cpp, I changed the last line of CARingBuffer::SetTimeBounds

from

CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);

to

mTimeBoundsQueuePtr++; 

OSAtomicCompareAndSwap DOES return a bool. What does the CA function do other than just call the OS function? The boolean result indicates whether the value was as expected. Your code is suspicious in that respect; are you sure it is correct?

What is the replacement for OSAtomicCompareAndSwap32Barrier?
 
 
Q