I have some question about boost::promise
After studying the website of boost and "C++ concurrency in action"
I still can't get the idea of boost::promise

According to the book(if I have no make any mistake)
boost::future is designed for one off event
you could wrap the task by packaged_task and let boost::unique_future
to gain the result of the task. When you launch the thread, you could
just return the boost::unique_future and wait for the result of the task.
After the task is finish, you could continue your job.
It is very like boost::condition_variable but design for one off event.
Do I make any mistake about it?

Assume that I didn't make any mistake about the idea of future, I still can't
get the idea of boost::promise, could you show me an easier example of it?

Thanks a lot

Recommended Answers

All 6 Replies

std::future<> and std::promise<> form a pair; together they provide an asynchronous inter-thread communication channel through which a value (or an exception) can be passed from one thread to another. std::promise<> is used by the function which wants to set a value, which can then be retrieved by another thread through the associated std::future<>.

std::packaged_task gives an easy to use wrapper over this: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2709.html

Looks like std::promise and std::package do the same thing
but std::promise give us a better control about the return value and exception
What are the cases would make us like to use std::promise rather than
std::package?Thanks

template<typename F>
std::unique_future<typename std::result_of<F()>::type> spawn_task(F f)
{
    typedef typename std::result_of<F()>::type result_type;
    std::packaged_task<result_type()> task(std::move(f)); #1
    std::unique_future<result_type> res(task.get_future());
    std::thread(std::move(task));
    return res;
}

What is the meaning of

result_type()

why don't just type

result_type

?
Thanks

> What are the cases would make us like to use std::promise rather than std::package?

std::future and std::promise are fairly low level, primitive constructs. AFAIK, these are expected to be the building blocks used to create high level abstractions (like lock-free data structures).

The basic idea is a good one - separate the communication channel (std::promise) from the thread creation and synchronization mechanisms. This allows a lot of flexibility in the creation of higher level constructs.


> What is the meaning of ...

typedef int result_type ;
std::packaged_task<result_type> // #1. is std::packaged_task<int>  
std::packaged_task< result_type() > // #2. is std::packaged_task< int() >

In #1, the template parameter is an int.
In #2, the template parameter is a nullary function which returns an int.

In #2, the template parameter is a nullary function which returns an int.

What should we set for the template parameter of the packaged_task?#1 or #2?
At first I think it is same as the return type of the function or functor

class test_package
{
  public :
    typedef bool result_type;		
    result_type operator()() 
    { 
      std::cout<<"this is test_package()"<<std::endl; 
      return true; 
    }
};

void test_packaged_task()
{
  ////boost::packaged_task<bool()> task4( boost::bind(test_package()) ); this one would fail	
  boost::packaged_task<bool> task4( boost::bind(test_package()) );
  boost::unique_future<bool> f4 = task4.get_future();
  boost::thread( std::move(task4) );
  f4.wait();
}

I am quite confuse about this, when should we use #2 instead of #1?
Thanks a lot

> What should we set for the template parameter of the packaged_task?#1 or #2?

#1 if the packaged_task is boost::packaged_task<> which is defined this way:

template< typename RESULT_TYPE > class packaged_task
{
    public:
        // construction and destruction
        template< typename FUNCTION_TYPE > explicit packaged_task( const FUNCTION_TYPE& f ) ;

        explicit packaged_task( RESULT_TYPE(*f)() ) ;

        template< typename FUNCTION_TYPE > explicit packaged_task( FUNCTION_TYPE&& f ) ;

        // ...

#2 if the packaged_task is std::packaged_task<> which is defined this way:

template<typename> class packaged_task ; // generalization is undefined

template< typename  RESULT_TYPE,  typename... ARG_TYPES >
class packaged_task< RESULT_TYPE( ARG_TYPES... ) > // what we use is this specialization
{
public:
    typedef RESULT_TYPE result_type;

    // construction and destruction
    packaged_task();

    template <typename FUNCTION_TYPE > explicit packaged_task( const FUNCTION_TYPE& f ) ;

    explicit packaged_task( RESULT_TYPE(*f)() ) ;

    template <typename FUNCTION_TYPE > explicit packaged_task( FUNCTION_TYPE&& f ) ;

    // ...

Using std::packaged_task<>

struct my_task : std::binary_function< bool, double, int >
{
    result_type operator() ( double d, int i ) const
    {
       return std::cout << "my_task: { " << d << ", " << i << " }\n" ;
    }
};

void test_it()
{
  std::packaged_task < bool( double, int ) > atask( my_task, 7.84, 6789 ) ;
  std::unique_future<bool> future( atask.get_future() ) ;
  std::thread( std::move( atask ) ) ;
  // do something
  future.wait() ;
}

Thanks a lot, with the help of variadic template
The codes become more natural

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.