c ++ 11 асинхронное продолжение или попытка семантики .then ()

Код ниже основан на Херб Саттерс идеи реализации продолжения типа .then ().

  template<typename Fut, typename Work>
auto then(Fut f, Work w)->std::future<decltype(w(f.get()))>
{ return std::async([=] { w(f.get()); }); }

Это будет использоваться как auto next = then(f, [](int r) { go_and_use(r); }); или похожие.

Это хорошая идея, но в ее нынешнем виде работать не будет (фьючерсы только перемещаются и не копируются). Мне действительно нравится эта идея, поскольку она, вероятно, появится в следующих версиях c ++, насколько я могу догадаться (хотя, как .then () или даже ожидаю.)

Перед тем, как сделать фьючерсы общими или похожими, мне интересно, что сообщество по переполнению стека подумает об этой реализации, особенно с улучшениями и предложениями (даже общими фьючерсами)?

Спасибо заранее за любые предложения.

(Я знаю, что это исправление, пока не существует основанный на стандартах механизм, так как он будет стоить потока (возможно)).

16

Решение

Я нахожу 3 проблемы с вышеупомянутой реализацией:

  • Это будет работать только если вы пройдете std::shared_future как Fut,
  • Возможно, продолжение будет иметь возможность обрабатывать исключения.
  • Он не всегда будет вести себя как положено, так как если вы не укажете std::launch::async оно может быть отложено, поэтому продолжение не вызывается так, как можно было бы ожидать.

Я пытался решить эти вопросы:

template<typename F, typename W, typename R>
struct helper
{
F f;
W w;

helper(F f, W w)
: f(std::move(f))
, w(std::move(w))
{
}

helper(const helper& other)
: f(other.f)
, w(other.w)
{
}

helper(helper&& other)
: f(std::move(other.f))
, w(std::move(other.w))
{
}

helper& operator=(helper other)
{
f = std::move(other.f);
w = std::move(other.w);
return *this;
}

R operator()()
{
f.wait();
return w(std::move(f));
}
};

}

template<typename F, typename W>
auto then(F f, W w) -> std::future<decltype(w(F))>
{
return std::async(std::launch::async, detail::helper<F, W, decltype(w(f))>(std::move(f), std::move(w)));
}

Используется так:

std::future<int> f = foo();

auto f2 = then(std::move(f), [](std::future<int> f)
{
return f.get() * 2;
});
7

Другие решения

Вот решение, протестированное с g ++ 4.8 и clang ++ 3.2:

template<typename F, typename W>
auto then(F&& f, W w) -> std::future<decltype(w(f.get()))>
{
cout<<"In thread id = "<<std::this_thread::get_id()<<endl;
return std::async(std::launch::async, w, f.get());
}

void test_then()
{
std::future<int> result=std::async([]{ return 12;});
auto f = then(std::move(result), [](int r) {
cout<<"[after] thread id = "<<std::this_thread::get_id()<<endl;
cout<<"r = "<<r<<endl;
return r*r;
});
cout<<"Final result f = "<<f.get()<<endl;
}
-1

По вопросам рекламы [email protected]