通过函数调用扩展C中局部变量的范围

时间:2014-01-08 10:07:36

标签: c windows multithreading

我有一个库,它为用户提供函数调用,如下所示:

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()并保持线程安全。

1 个答案:

答案 0 :(得分:1)

您可以在此处使用threadlocal来保留g_ID,而不是使用全局。根据我的理解,这将在场景中起作用,来自不同线程的process()可能有多个并发调用,但process()方法如图所示 - SendResponse()调用只会出现在callback()方法的范围(运行时范围,而不是词法)中。在显示的代码中也是如此。如果HandleRequest做了异乎寻常的事情,比如启动另一个线程然后返回(但你当然可以通过文档禁止它),这可能是不正确的。

另一种更经典的方法是将您关注的所有状态(如g_ID)封装到传递给回调的void *opaque_state *或其他任何内容中,然后再封装方法像SendRespose()那样把它作为一个论点。如果您不喜欢void *,则可以使用前向声明实现opaque_state *版本,而不会暴露该结构的任何细节。