我有一个库,它为用户提供函数调用,如下所示:
int* g_ID = NULL;
void processing(int p1, char p2)
{
int ID = newID();
g_ID = &ID;
callback(p1, p2);
return ID;
}
void SendResponse()
{
sendID(*g_ID);
}
用户通过使用签名void (f*)(int p1, char p2)
注册其回调函数来设置其应用程序,并且不应该知道库内部使用的ID。因此用户空间代码如下所示:
main()
{
RegisterCallback(HandleRequest);
while (inProgress())
sleep(1); /* just sleep here */
}
void (HandleRequest*)(int val1, char val2)
{
/* ... do something user specific ... */
SendResponse();
return;
}
这里的问题是,库(处理ID和g_ID
不是线程安全的)!!用户的回调由其他库函数异步调用,如线程。可以通过这种方式并行执行多个线程。但我不会让用户看到库内部ID。
我知道上面的代码片段并不完美。只是为了表明我的意图...... SendResponse()
尚未实施; - )。
我希望,有人可以提出一些想法,如何“实施”SendResponse()
并保持线程安全。
答案 0 :(得分:1)
您可以在此处使用threadlocal来保留g_ID,而不是使用全局。根据我的理解,这将在场景中起作用,来自不同线程的process()
可能有多个并发调用,但process()
方法如图所示 - SendResponse()
调用只会出现在callback()
方法的范围(运行时范围,而不是词法)中。在显示的代码中也是如此。如果HandleRequest做了异乎寻常的事情,比如启动另一个线程然后返回(但你当然可以通过文档禁止它),这可能是不正确的。
另一种更经典的方法是将您关注的所有状态(如g_ID)封装到传递给回调的void *
或opaque_state *
或其他任何内容中,然后再封装方法像SendRespose()
那样把它作为一个论点。如果您不喜欢void *
,则可以使用前向声明实现opaque_state *
版本,而不会暴露该结构的任何细节。