1

我正在使用具有阻塞功能的第三方库,也就是说,它在完成之前不会返回;我可以为该呼叫设置超时。

问题是,该函数将库置于某种状态。一旦它进入那个状态,我需要用我自己的代码做一些事情。我的第一个解决方案是在单独的线程中执行此操作:

void LibraryWrapper::DoTheMagic(){
    //...
    boost::thread EnteredFooStateNotifier( &LibraryWrapper::EnterFooState, this );
    ::LibraryBlockingFunction( timeout_ );
    //...
}

void LibraryWrapper::EnterFooState(){
   ::Sleep( 50 ); //Ensure ::LibraryBlockingFunction is called first
   //Do the stuff
}

很恶心,不是吗?我不得不Sleep打电话因为 ::LibraryBlockingFunction 必须在我下面做的事情之前被调用,否则一切都会失败。但是等待 50 毫秒是一个很差的保证,我不能再等了,因为这个特定的任务需要尽快完成。

难道没有更好的方法来做到这一点吗?考虑到我无权访问图书馆的代码。欢迎使用 Boost 解决方案。

更新:就像其中一个答案所说,库 API 定义不明确。我向开发人员发送了一封电子邮件,解释了问题并提出了解决方案(即,使呼叫非阻塞并将事件发送到已注册的回调以通知状态更改)。同时,我设置了足够高的超时时间以确保完成 X 工作,并在执行调用后工作之前设置足够高的延迟时间以确保调用库函数。它不是确定性的,但在大多数情况下都有效。

4

2 回答 2

2

使用 boost future 会澄清这段代码吗?要使用boost future 文档中的示例:

int calculate_the_answer_to_life_the_universe_and_everything()
{
    return 42;
}

boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost::unique_future<int> fi=pt.get_future();

boost::thread task(boost::move(pt));

// In your example, now would be the time to do the post-call work.

fi.wait(); // wait for it to finish

尽管您可能仍然需要一些延迟以确保您的函数调用已经发生(您的问题的这一点似乎定义不明确-有什么方法可以确定性地确定何时可以安全地执行后-调用状态更改?)。

于 2012-06-22T20:42:12.443 回答
2

据我了解,问题是您需要这样做:

  1. 输入阻止呼叫
  2. 在你进入阻塞调用之后但在它完成之前,你需要做一些其他的事情
  3. 您需要在阻塞调用返回之前完成#2

从纯粹的 C++ 角度来看,您无法以确定性的方式实现这一点。那是在不了解您正在使用的库的详细信息的情况下。

但我注意到你的超时值。这可能会提供一个漏洞,也许。

如果你:

  1. 输入超时为零的阻塞调用,使其立即返回
  2. 你有其他东西吗,要么在同一个线程中,要么与主线程同步。也许使用屏障。
  3. 验证#2 完成后,再次进入阻塞调用,正常的非零超时。

仅当您输入具有零超时的阻塞调用时,库的状态将发生更改,这才有效。

于 2012-06-22T21:04:39.380 回答