gpt4 book ai didi

c++ - 在 C++17 中,是否未定义使用无锁原子保护从信号处理程序传递的数据?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:40:31 26 4
gpt4 key购买 nike

根据我对过去问题的阅读,该标准允许在信号处理程序中访问无锁原子,并且对“普通”对象的任何修改都变得未定义。如果是这样,下面的模式,其中原子变量是非原子变量的内存屏障,也是未定义的吗?

下面的模式是一个单一的生产者信号消费者环形缓冲区。信号是生产者,线程是消费者。请忽略正在旋转的收集线程的低效率 - 不想让一个已经很复杂的例子复杂化。

AFAICT,这种模式在信号处理程序中使用是安全的,因为原子变量可以防止任何竞争,而且我避免了信号处理程序内部的内存分配。但是,它确实会修改信号处理程序中的非原子对象。

vector<vector<int>> ring;
atomic<int> push_idx;
atomic<int> pop_idx;

void init()
{
ring.resize(8);
for (auto &v : ring)
{
v.resize(10);
}
}

int advance_idx(int i)
{
return (i + 1) % 8;
}

int buf[5];

void sig_handler()
{
int a = push_idx.load(memory_order_relaxed);
int p = pop_idx.load(memory_order_acquire);
if (advance_idx(a) == p)
{
return; // ring overflow
}

// fill up static-linkage data
for (int i = 0; i < 5; i++)
{
buf[i] = i;
}

// copy some static-linkage data into buffer
for (int i = 0; i < 5; i++)
{
ring[a][i] = buf[i];
}
ring[a].resize(5);
push_idx.store(advance_idx(a), memory_order_release)
}

void collecting_thread()
{
for (;;)
{
int p = pop_idx.load(memory_order_relaxed);
int a = push_idx.load(memory_order_acquire);
if (p == a)
{
continue; // nothing to do
}

auto &vec_to_process = ring[p];
process_vec(std::move(vec_to_process); //may move-from
vec_to_process.clear();
vec_to_process.resize(10);
pop_idx.store(advance_idx(p), memory_order_release);
}
}

最佳答案

根据评论回答我自己的问题 - 它似乎是未定义的行为,一如既往。

在对 sem_post, signal handlers, and undefined behavior 的回答中(这是关于 POSIX 的),它是未定义的,不是因为它与信号、线程、原子或 CPU 的工作方式相矛盾,而是因为指定正确的行为很困难而且没有显着的 yield 。

在大多数情况下,处理信号的正确做法是在信号处理程序中设置一个标志,或者“接受信号”(sigwait() 等)。在我的例子中,这是行不通的,因为我需要获取堆栈跟踪(SIGPROF 处理程序)并将其传递给应用程序。

关于c++ - 在 C++17 中,是否未定义使用无锁原子保护从信号处理程序传递的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51941811/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com