Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Async operation on a tree

I am implementing a tree data structure and some operations on it. Every node has some value, pointer to its parent and list of its children. I have implemented a function max_value which recursively travels through the tree and finds highest value stored in nodes. Now, I would like to implement an async function which does the same, using the C++11 standard. I have the following code:

template<typename T>
T Node<T>::max_value_async(void)
{
    T current_value = p_value;
    list<future<T>> results;
    //launch tasks
    for ( auto x : p_children)
    {
        results.insert(async(std::launch::async, x.max_value));
    }
    //wait for results
    for (auto r : results)
        r.wait();
    //find highest value
    for (auto r : results)
    {
        if (current_value < r.get())
            current_value = r.get();
    }

    return current_value;
}

but I have troubles launching the async function. What's wrong?

like image 723
user1453857 Avatar asked Dec 27 '25 16:12

user1453857


1 Answers

There are a few issues:

  • First, there's no need to use wait() since that's implied by get().
  • Either list or vector works fine with push_back. You give the wrong number of arguments to list::insert. The best is to use in-place construction with emplace_back
  • It also seems you should only do .get() once. Subsequent calls to get() yields std::future_error exception.
  • The syntax you used for constructing the futures does not exist. The simplest way to do things like that is with a lambda as below.

Full example:

// g++ -pthread -std=c++0x 
#include <iostream>
#include <future>
#include <list>

struct X {
  X(int v) : mv(v) {}
  int mv;
  int max_value() const {
    return mv;
  }
};

int main(){
  std::list<std::future<int> > results;
  X x4(4);
  X x5(5);
  X x3(3);

  results.emplace_back(std::async(std::launch::async, 
    [&x4](){ return x4.max_value();}));
  results.emplace_back(std::async(std::launch::async, 
    [&x5](){ return x5.max_value();}));
  results.emplace_back(std::async(std::launch::async, 
    [&x3](){ return x3.max_value();}));

  // for sure there's better ways to do this step, but for clarity:
  int best_value=0;
  for (auto &r : results){
      auto this_value=r.get();
      if (best_value < this_value)
        best_value = this_value;
    }

  std:: cout << best_value << std::endl;
}

Since you use a shared pointer you could also make the lambda take the object by value,

std::shared_ptr<SomeT> some_obj= ... from somewhere... ;
results.emplace_back(
   std::async(
     std::launch::async, [some_obj](){ return some_obs->max_value();}
   )
);
like image 87
Johan Lundberg Avatar answered Dec 30 '25 04:12

Johan Lundberg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!