Thursday, November 8, 2012

What is std::async ?

The new C++0x standard has provided many new and powerful tools for a c++ coders arsenal. Unfortunately I have already started to see several cases of copy the book coding. It is all to easy to forget that these tools are just slightly more complex constructs of the more fundamental units.

It is often a very enlightening experience to reinvent the wheel and understand what the original creators had to go through. Rather than just being another just another fool "standing on the shoulders of giants". Just another one of the new generation of school kids that cant add numbers together without a calculator.

So on that note i got curious about how the std::async works. On the surface its seems rather simple, but to actually create it I took several wrong turns. and learned a bit on the way.

There are several lessons that got me here:
* Look carefully at the the Lambda(and also a std::bind) and note that it cant take move schematics. As a result the promise is on the heap and a pointer...
* Note that my imatate_async requires the template param to be filled in. I have missed some trick that the std::async has that allows it to deduce the actual return type of the function.
* Note that this version doesn't account for parameters being passed to the thread function... Im lazy get over it.
* Note the exception catch a generic ... with a std:: function to pull down the actual throw. otherwise you up for std::terminate killing your app when that unexpected throw comes out.. its a bonus that this is a nice way to pass the exception to a different stack.

#include <iostream>
#include <thread>
#include <future>

// thread vs async.

int test_func() 
{
  return 1; 
}

template< class R >
std::future<R> async_imitate(std::function<R(void)> func)
{ 
  std::promise<R>* p = new std::promise<R>();

  std::function<void(void)> wrapper = 
    [p,func]()->void
    {
      try
 {
   p->set_value(func());
 }
      catch(...)
 {
   p->set_exception(std::current_exception());
 }
      delete p;
    };

  std::thread t(wrapper);
  t.detach();
  return p->get_future();
}

void run_thread()
{
  std::cout << "start run_thread\n";
  
  std::future<int> ret = async_imitate<int>(&test_func);
  int i = ret.get();
  std::cout << "run_thread: " << i << "\n";
}

void run_async()
{
  std::cout << "start run_async\n";

  std::future<int> ret = std::async(&test_func);
  int i = ret.get();
  std::cout << "run_async: " << i << "\n";
}

int main()
{
  run_async();
  run_thread();
}

No comments:

Post a Comment