How to refactor old Apple SDK files displaying build warnings in C++ with OSAtomicCompareAndSwap32()?

huangapple go评论75阅读模式
英文:

How to refactor old Apple SDK files displaying build warnings in C++ with OSAtomicCompareAndSwap32()?

问题

我遇到了一些构建警告,使用了一些较旧的苹果SDK文件,我正试图重构以消除这些警告。
我对语法感到困惑,希望有人能帮助解释一下。

一个示例调用是
OSAtomicCompareAndSwap32(mWriteIndex,(mWriteIndex + 1) & mMask,&mWriteIndex);
您能帮忙解释 (mWriteIndex + 1) & mMask 吗?

所有参数都被定义为 int32_t 类型。

我尝试使用错误消息中描述的 std::atomic_compare_exchange_strong_explicit,但是使用以下代码出现了“没有匹配的函数调用”:

std::atomic<int32_t> mReadIndex, mWriteIndex, mFreeIndex;

std::atomic_compare_exchange_strong_explicit(&mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex, std::memory_order_relaxed, std::memory_order_relaxed);

'OSAtomicCompareAndSwap32' 已弃用:在macOS 10.12中首次弃用 - 请使用 std::atomic_compare_exchange_strong_explicit(std::memory_order_relaxed)

英文:

I've got some build warnings using some older Apple SDK files, which I'm attempting to refactor to silence the warnings.
I'm confused by the syntax, and hoped someone might be able to help explain it.

An example call is
OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex);
Could you please help to explain (mWriteIndex + 1) & mMask ?

All arguments are defined as int32_t types.

I've tried to use std::atomic_compare_exchange_strong_explicit as described by the error message, but am getting No matching function for call using

std::atomic<int32_t> mReadIndex, mWriteIndex, mFreeIndex;

std::atomic_compare_exchange_strong_explicit(&mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex, std::memory_order_relaxed, std::memory_order_relaxed);

'OSAtomicCompareAndSwap32' is deprecated: first deprecated in macOS 10.12 - Use std::atomic_compare_exchange_strong_explicit(std::memory_order_relaxed)

答案1

得分: 1

有关:

(mWriteIndex + 1) & mMask

mWriteIndex + 1 当然是将 mWriteIndex 增加一。

假设 mMask 是一个整数,只有一些最低有效位设置为1,那么 & mMask 的部分是一种旧技巧,用于计算 (mWriteIndex + 1) 的模数,而无需进行实际的除法/模运算——例如,如果您想要计算 x % 16,那么 x & 0x0F 将给您相同的结果,可能使用更少的CPU周期,因为按位与操作传统上比divmod操作快。当然,这个技巧只适用于计算2的幂的模数。

您呈现的代码很可能实现了一个无锁的循环FIFO队列;在这个方案中,循环数组的大小将始终设置为2的幂,特别是为了使这个技巧起作用。

关于将 OSAtomicCompareAndSwap32() 函数调用升级为其现代/标准C++替代品,我认为您想要的是这样的代码:

int32_t expectedVal = mWriteIndex.load();
mWriteIndex.compare_exchange_strong(expectedVal, (mWriteIndex + 1) & mMask, std::memory_order_release, std::memory_order_relaxed);
英文:

Regarding:

(mWriteIndex + 1) & mMask

mWriteIndex + 1 is, of course, adding one to mWriteIndex.

Assuming mMask is an integer with only some number of the least-significant-bits set, then the & mMask part is an old trick to compute a modulo of (mWriteIndex + 1) without having to actually do a division/modulo operation -- e.g. if you wanted to compute x % 16, then x & 0x0F will give you the same result while potentially using fewer CPU cycles, as a bitwise-AND is traditionally faster than a divmod operation. That trick only works for doing a modulo of a power-of-two, of course.

The code you present is most likely implementing a lock-free circular FIFO queue; in this scheme the size of the circular array will always be set to a power-of-two, specifically to allow this trick to work.

Regarding the upgrading of the OSAtomicCompareAndSwap32() function call to its modern/standard-C++ replacement, I think you want something like this:

int32_t expectedVal = mWriteIndex.load();
mWriteIndex.compare_exchange_strong(expectedVal, (mWriteIndex + 1) & mMask, std::memory_order_release, std::memory_order_relaxed);

huangapple
  • 本文由 发表于 2023年6月5日 11:15:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76403299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定