5

I try to work with boost thread futures. So as shown here we can get shared future from packaged task.

So I try such function on linux:

template <class task_return_t>
void pool_item( boost::shared_ptr< boost::packaged_task<task_return_t> > pt)
{
    boost::shared_future<task_return_t> fi= pt->get_future(); // error
    //...

but I get error calling it:

../../src/cf-util/thread_pool.h: In member function ‘void thread_pool::pool_item(boost::shared_ptr<boost::packaged_task<R> >) [with task_return_t = void]’:
../../src/cf-util/thread_pool.h:64:3:   instantiated from ‘void thread_pool::post(boost::shared_ptr<boost::packaged_task<R> >) [with task_return_t = void]’
../../src/cf-server/server.cpp:39:27:   instantiated from here
../../src/cf-util/thread_pool.h:124:58: error: conversion from ‘boost::unique_future<void>’ to non-scalar type ‘boost::shared_future<void>’ requested

I did not take any futures from that task before. all source code, place where I do call from, my thread pool that is being called. And on Windows under Visual Studio 2010 it compiles and works perfectly.

What shall I do? how to fix or get around this error?

Nathan Kleyn
  • 5,103
  • 3
  • 32
  • 49
Rella
  • 65,003
  • 109
  • 363
  • 636
  • Perhaps a version problem? I can convert a `unique_future` to a `shared_future` just fine on my end. – Luc Danton Aug 31 '11 at 03:48
  • @Luc Danton: Show me how and I will try it!) Secondly problem is I pass tasks to my task manager that than sends tham into this function. So problem here is that `unique_future` can be already taken\assigned and be on `.wait();` for example. – Rella Aug 31 '11 at 03:54
  • Like you're attempting: `boost::shared_future f = task.get_future();` where `task` is `boost::packaged_task task;`. (Your second problem sounds like it warrants a separate question.) – Luc Danton Aug 31 '11 at 03:58

4 Answers4

4

The conversion from unique_future to shared_future uses the following constructor in the documentation:

shared_future(unique_future<R> && other);

This uses an rvalue reference to ensure that it's clear in the source code that you intended to destroy the value of 'other'. It's possible that VC++2010 provides enough rvalue reference support by default to support that directly, while the compiler you're using on linux (probably gcc) requires an extra flag like -std=gnu++0x to support it. Without that flag, boost falls back to "move emulation", which might (I haven't checked this) require you to write:

boost::shared_future<task_return_t> fi = boost::move(pt->get_future());
Jeffrey Yasskin
  • 5,171
  • 2
  • 27
  • 39
1

Jeffrey Yasskin is correct. The function compiles with g++ (4.6.3) on Linux with the -std=gnu++0x flag, or with the -std=c++0x flag if you want strictly ISO compilation. These -std flags are now deprecated in favour of gnu++11 and c++11 respectively. (I'd have just made this a comment but don't yet have sufficient privelege)

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • -std=gnu++11 is only supported with gcc-4.7 and above and clang-3.0 or -3.1 and above, so I haven't decided whether I prefer code to use it or the "0x" spelling. In the long run, yes, the "11" spelling will be preferred. – Jeffrey Yasskin May 13 '12 at 22:42
0

In C++11 you should call std::future::share() to obtain a shared_future from a future. E.g.,

auto sf=std::async([]{/* something */}).share();
PeterSom
  • 2,067
  • 18
  • 16
0

Is it possible you forgot to include the right headers?

If not, does a different constructor like the one below work?

boost::shared_future<task_return_t> fi(pt->get_future());
tgoodhart
  • 3,111
  • 26
  • 37