阻塞代码和回调。如何将阻塞代码转换为非阻塞代码?
Blocking code and callbacks. How to to transform blocking code in non-blocking code?
我觉得这个问题的核心与我使用的具体语言和库无关,所以我使用了一些伪代码。我们可以假设 C 是一种语言和一个 WinApi COM DLL。
假设我正在使用一个动态链接的外部库,它公开了一些回调以响应某些事件。说:
function RegisterCallback(ptr *callback);
将用作:
function OnEvent(type newValue) {
...
}
...
RegisterCallback(&OnEvent)
...
库告诉我回调应该非阻塞。
现在,假设我想更新一个内部状态来响应这个事件。此内部状态由其他线程访问,因此由 mutex 保护。因此我想写:
function OnEvent(type newValue) {
mutexLock();
internalState = newState;
mutexUnlock()
}
但这可能是一个阻塞操作。我该如何进行?我看到的唯一解决方案是使用不同的线程来更新状态,例如:
function OnEvent(type newValue) {
sendChangeStateMessage(newValue)
}
但是,再次强调,为了使这个调用成为非阻塞的,这个“发送操作”应该被缓冲(即,有一个消息队列),因为跨线程发送(即共享数据)需要同步,因此锁定。
编辑:当然,如果操作是原子操作(可能是整数),则没有这样的问题/编辑
总结一下:如何将阻塞代码转换为非阻塞代码?
谢谢
使用互斥量锁定并不总是阻塞操作。
如果互斥量仅用于保护对那个变量的访问,并且如果所有其他获取该互斥量的线程在互斥量被锁定时不执行任何阻塞操作,那么这不是阻塞操作。阻塞操作是一种将阻塞直到发生某些事情的操作。在这种情况下,这种互斥锁的使用不太可能被阻塞,例如,除非您将互斥锁锁定在另一个线程中并等待网络读取。
我觉得这个问题的核心与我使用的具体语言和库无关,所以我使用了一些伪代码。我们可以假设 C 是一种语言和一个 WinApi COM DLL。
假设我正在使用一个动态链接的外部库,它公开了一些回调以响应某些事件。说:
function RegisterCallback(ptr *callback);
将用作:
function OnEvent(type newValue) {
...
}
...
RegisterCallback(&OnEvent)
...
库告诉我回调应该非阻塞。 现在,假设我想更新一个内部状态来响应这个事件。此内部状态由其他线程访问,因此由 mutex 保护。因此我想写:
function OnEvent(type newValue) {
mutexLock();
internalState = newState;
mutexUnlock()
}
但这可能是一个阻塞操作。我该如何进行?我看到的唯一解决方案是使用不同的线程来更新状态,例如:
function OnEvent(type newValue) {
sendChangeStateMessage(newValue)
}
但是,再次强调,为了使这个调用成为非阻塞的,这个“发送操作”应该被缓冲(即,有一个消息队列),因为跨线程发送(即共享数据)需要同步,因此锁定。
编辑:当然,如果操作是原子操作(可能是整数),则没有这样的问题/编辑
总结一下:如何将阻塞代码转换为非阻塞代码?
谢谢
使用互斥量锁定并不总是阻塞操作。
如果互斥量仅用于保护对那个变量的访问,并且如果所有其他获取该互斥量的线程在互斥量被锁定时不执行任何阻塞操作,那么这不是阻塞操作。阻塞操作是一种将阻塞直到发生某些事情的操作。在这种情况下,这种互斥锁的使用不太可能被阻塞,例如,除非您将互斥锁锁定在另一个线程中并等待网络读取。