我目前在Windows上使用Boost 1.55 BOOST_THREAD_VERSION=2
,BOOST_THREAD_PROVIDES_FUTURE
和BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
。
在单元测试中,延续似乎表现得很好,但在实际代码中它会死锁。
基本代码结构在生产者方面看起来像这样:
typedef std::map<std::string, std::string> Dictionary;
struct Operation
{
std::unique_ptr<boost::promise<Dictionary>> m_promise;
boost::future<Dictionary> Start(const Dictionary& data)
{
m_promise.reset(new boost::promise<Dictionary>());
// pass off work to something else
// it runs asynchronously then calls Complete
return m_promise->get_future();
}
void Complete(const Dictionary& result)
{
m_promise->set_value(result);
m_promise.reset();
}
};
消费者方面看起来像这样:
m_Operation.Start(data).then([=](boost::future<Dictionary> f)
{
// ...
DoSomething(f.get());
});
return true;
继续被调用,但f.get()
无限制地阻塞,set_value
也是如此。
据我所知,一个帖子在promise::set_value
内被阻止(特别是future_async_shared_state_base::join()
),另一个被future::get()
阻止(特别是shared_state_base::wait()
中的互斥})。
(看起来set_value()
中的线程试图在获取get()
被阻止的相同互斥锁后破坏延续。)
这是在Boost的更高版本中修复的错误,我使用的是不受支持的配置,还是我在做其他错误?
我不希望因任何原因阻止任何事情发生。它应该只是一个简单的回调&amp;越区切换。
此外,我很困惑为什么延续在一个单独的线程上执行,而不是在set_value
内执行。没有一个可能的启动策略似乎支持同步运行延续,我认为这将是自然默认(这就是.NET Tasks的行为)。我真的更喜欢不启动新线程来运行延续,因为这最终只会将工作发布到Asio服务。
或者期货只是这种事情的错误模型?我试过制作一个Asio异步方法,但很快就迷失在样板中。