目前我們使用的異步值非常大。 假設我有一個函數,確實是這樣的:未來轉換模式
int do_something(const boost::posix_time::time_duration& sleep_time)
{
BOOST_MESSAGE("Sleeping a bit");
boost::this_thread::sleep(sleep_time);
BOOST_MESSAGE("Finished taking a nap");
return 42;
}
在某些時候,在代碼中創建它創建了一個未來將由一個packaged_task被設置成一個int值的任務 - 像這樣(worker_queue是一個boost :: ASIO :: io_service對象在這個例子中):
boost::unique_future<int> createAsynchronousValue(const boost::posix_time::seconds& sleep)
{
boost::shared_ptr< boost::packaged_task<int> > task(
new boost::packaged_task<int>(boost::bind(do_something, sleep)));
boost::unique_future<int> ret = task->get_future();
// Trigger execution
working_queue.post(boost::bind(&boost::packaged_task<int>::operator(), task));
return boost::move(ret);
}
在代碼另一點我想換這個函數返回一些更高級別的對象也應該是未來。我需要一個轉換函數,它接受第一個值並將其轉換爲另一個值(在我們的實際代碼中,我們有一些分層並執行異步RPC,將期貨返回給響應 - 這些響應應該轉換爲期貨到實際對象,POD甚至無效未來能夠等待或捕獲例外)。因此,這是在這個例子中,轉換功能:
float converter(boost::shared_future<int> value)
{
BOOST_MESSAGE("Converting value " << value.get());
return 1.0f * value.get();
}
然後,我認爲是在加速文檔描述只做如果想這種轉換創建一個懶惰的未來:
void invoke_lazy_task(boost::packaged_task<float>& task)
{
try
{
task();
}
catch(boost::task_already_started&)
{}
}
然後,我有功能(可能是一個更高層次的API)來創建一個包裹未來:
boost::unique_future<float> createWrappedFuture(const boost::posix_time::seconds& sleep)
{
boost::shared_future<int> int_future(createAsynchronousValue(sleep));
BOOST_MESSAGE("Creating converter task");
boost::packaged_task<float> wrapper(boost::bind(converter, int_future));
BOOST_MESSAGE("Setting wait callback");
wrapper.set_wait_callback(invoke_lazy_task);
BOOST_MESSAGE("Creating future to converter task");
boost::unique_future<float> future = wrapper.get_future();
BOOST_MESSAGE("Returning the future");
return boost::move(future);
}
最後我希望能夠利用這樣的:
{
boost::unique_future<float> future = createWrappedFuture(boost::posix_time::seconds(1));
BOOST_MESSAGE("Waiting for the future");
future.wait();
BOOST_CHECK_EQUAL(future.get(), 42.0f);
}
但是,在這裏我最終得到了一個關於違約承諾的例外。原因似乎對我來說很清楚,因爲執行轉換的packaged_task超出了範圍。
所以我的任務是:我如何處理這種情況。我怎樣才能防止任務被破壞?有這樣的模式嗎?
最好成績,
羅尼
我想創建一個自己的類,它提供了與boost :: ..._ future相同的接口來保存任務,並將所有接口調用委託給任務提供的未來。但是必須有更好的解決方案。 – duselbaer
是否有理由不能包裝正在評估的函數,以便在任務被調用時完成轉換? –
@DaveS主要問題是這些函數是我們軟件中不同圖層的一部分。 createAsynchronousValue方法對應於由RPC消息傳遞層管理的RPC-Request。我會考慮的 ...:) – duselbaer