gpt4 book ai didi

c - 我应该如何在不使用锁的情况下在另一个线程的回调中注册更新?

转载 作者:太空狗 更新时间:2023-10-29 15:24:57 25 4
gpt4 key购买 nike

这是似乎属于“天真明显但可能是错误的”类别的问题之一。当然,我正在努力寻找适用于所有极端情况的解决方案。看来这一定是一个经常遇到的问题。

我有一个“硬件”线程和一个“处理”线程。

硬件线程在我无权访问的封闭二进制库中运行。

处理线程向硬件线程注册回调,以通知与硬件状态更改相关的某些(罕见)事件。

我希望能够通知处理线程中的事件循环状态已经改变。我想这样做而不需要依赖外部库或以不可移植的方式,并且不使用锁(因为我不知道硬件线程何时可能想要再次通知处理线程)。

所以,我目前对于如何解决这个问题的想法是这样的:

#include <signal.h>

// sig_atomic_t is used so update is always in a sane state
static volatile sig_atomic_t update = 0;

// called from hardware thread
int callback_function() {
update += 1;
}

// called regularly from processing thread
int processing_function() {
static sig_atomic_t local_update = 0; // The same type as update

if (local_update != update){
update_internal_hardware_state(); // We necessarily call once per callback
local_update += 1;
}
}

很明显,如果 update 回绕并且恰好在下一次调用 processing_function 之前达到 local_update 的值,这将会中断(尽管几乎可以肯定我可以假设这永远不会发生)。

我是否在这里错过了一些微妙的(或不那么微妙的)东西?

有没有更好的方法来解决整个问题?

可以假定回调仅从一个线程(硬件线程)调用。

最佳答案

一个选项是使用标准 unix self-pipe trick .好处是管道的读取端可以与 select()epoll() 一起使用,从而与 event loops 很好地集成。无需定期轮询原子变量的值。

#include <unistd.h>
#include <errno.h>

int self_pipe[2]; // the read end is non-blocking

// called from hardware thread
int callback_function() {
write(self_pipe[1], "", 1); // notify by writing a byte
return 0;
}

// called only when self_pipe[0] is ready for read
int processing_function() {
for(;;) {
char buf;
ssize_t n = read(self_pipe[0], &buf, 1);
if(n > 0) {
// callback_function() has been called
}
else if(n < 0) {
if(EAGAIN == errno)
break;
// handle an (unlikely) error
}
else {
// handle pipe EOF if necessary
}
}
return 0;
}

如果您使用的是 Linux >= 2.6.22 而不是管道,您可以使用 eventfd ,它基本上是一个在内核中维护的信号量,并通过 read()write() 系统调用进行操作。同样,它的好处是它可以与事件循环一起使用。

关于c - 我应该如何在不使用锁的情况下在另一个线程的回调中注册更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7801664/

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