release()为了简单起见,libc++的shared_ptr实现可以描述为:
void release()
{
if (ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1)
{
delete this;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么libc++不把它分成release decrement和acquisition fence呢?
void release()
{
if (ref_count.fetch_sub(1, std::memory_order_release) == 1)
{
std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
}
Run Code Online (Sandbox Code Playgroud)
正如Boost 建议的那样,这看起来很优越,因为它不会对除最后一个减量之外的所有内容强加获取内存顺序。
我现在正在学习C++ 11内存阶模型,并想明白之间的差别memory_order_relaxed和memory_order_consume.
具体而言,我正在寻找一个简单的例子,其中一个不能代替memory_order_consume用memory_order_relaxed.
有一篇很好的文章详细阐述了一个memory_order_consume可以应用的简单但非常具有说明性的例子.下面是文字复制粘贴.
例:
atomic<int*> Guard(nullptr);
int Payload = 0;
Run Code Online (Sandbox Code Playgroud)
制片人:
Payload = 42;
Guard.store(&Payload, memory_order_release);
Run Code Online (Sandbox Code Playgroud)
消费者:
g = Guard.load(memory_order_consume);
if (g != nullptr)
p = *g;
Run Code Online (Sandbox Code Playgroud)
我的问题包括两部分:
memory_order_consume用memory_order_relaxed在上面的例子?memory_order_consume不能被替换memory_order_relaxed?TL;DR:在生产者-消费者队列中,放置一个不必要的(从 C++ 内存模型的角度来看)内存栅栏或不必要的强内存顺序是否有必要以牺牲可能更差的吞吐量为代价来获得更好的延迟?
C++ 内存模型是在硬件上执行的,方法是使用某种内存栅栏来实现更强的内存顺序,而不是将它们放在较弱的内存顺序上。
特别是,如果生产者这样做store(memory_order_release),而消费者使用 观察存储的值load(memory_order_acquire),则加载和存储之间没有围栏。在 x86 上根本没有栅栏,在 ARM 上栅栏是在存储之前和加载之后进行放置操作。
没有围栏存储的值最终会被没有围栏的负载观察到(可能在几次不成功的尝试之后)
我想知道在队列的两侧放置围栏是否可以更快地观察到值?如果有围栏和没有围栏,延迟是多少?
我希望只有一个循环load(memory_order_acquire)和pause/yield限制为数千次迭代是最好的选择,因为它无处不在,但想了解原因。
由于这个问题是关于硬件行为的,我希望没有通用的答案。如果是这样,我主要想知道 x86(x64 风格),其次是 ARM。
例子:
T queue[MAX_SIZE]
std::atomic<std::size_t> shared_producer_index;
void producer()
{
std::size_t private_producer_index = 0;
for(;;)
{
private_producer_index++; // Handling rollover and queue full omitted
/* fill data */;
shared_producer_index.store(
private_producer_index, std::memory_order_release);
// Maybe barrier here or stronger order above?
}
}
void consumer()
{
std::size_t private_consumer_index = 0;
for(;;)
{
std::size_t observed_producer_index = shared_producer_index.load( …Run Code Online (Sandbox Code Playgroud)