0

My code calls a function from 3rd party library. Let's call this function SomeFunc

void SomeFunc(void (*callBack) (int));

As you can see SomeFunc takes a callback function parameter. Once SomeFunc is called, the calling thread will progress, and the library will execute the callback several time on a different thread -- passing it different status code.

My requirement is the thread that calls SomeFunc (aka main thread) should wait until certain status code is passed to the callback. So far I have something like this

CEvent *pEvt = NULL;

void myCallBack(int code) {
  if(code == SOME_MAGIC_NUM) pEvt->SetEvent(); // signal thread waiting for this event obj they can continue
}

int main (int argc, char** argv) {
  pEvt = new CEvent(FALSE, TRUE);
  SomeFunc(myCallBack); // This doesn't block, main thread will progress to next line
  WaitForSingleObject(pEvt, 5000); // wait here until 3rd party library call myCallBack with code SOME_MAGIC_NUM -- or if it doesn't after 5 seconds, continue

  // do interesting stuff here..

  return EXIT_SUCCESS;
}

Now this seem fine if I only do this on the main thread / main function like above. However if multiple thread can execute the code block in main above, my problem is they will share reference to the global pEvt variable, and it will mess up

What's the best code design approach I should take here? Ideally I would like to change the callback function signature to accept reference to the CEvent object, but since it's a 3rd party library I'm unable to do that.

4

2 回答 2

0

你真的想要javascript中的闭包。您可以通过每次将函数调用绑定到新的 CEvent 对象来完成类似的操作。看看std::bind1stboost::bind

另请参阅此stackoverflow 线程

于 2013-04-02T06:42:46.577 回答
0

您只能实现这一点,因为第 3 方提供了一种将“自定义”参数传回回调的方法。精心设计的 API 允许设置回调void* 值,并且回调在调用时接收此参数。从这个 void* 你可以通过不安全的转换扩展到任何你喜欢的东西,包括对象和方法调用。所有基于绑定或成员函数地址或其他任何解决方案最终归结为同一个问题:必须以某种方式将this*其传递回回调。

例如,请参阅BIO_set_callback:它允许您设置回调回调任意参数。请注意,callabck 参数可以是间接的,例如在 gnutls 中:可以将参数设置为会话中的任意数据gnutls_session_set_ptr,然后在回调中使用gnutls_session_get_ptr. 您的第 3 方可能会提供这种间接方法。

如果图书馆不提供这样的功能,那么你就会陷入困境。例如,您可以拥有一组“可用”回调,每个回调都与特定事件相关联(即不同的函数作为地址,尽管代码相同)。您选择一个回调并将其从集合中移除并放置,然后等待与回调关联的事件。完成后,将回调放回可用列表中。“可用”列表的大小在编译时是硬编码的,因为您确实需要单独的函数,每个回调一个函数。

于 2013-04-02T06:51:24.503 回答