Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can an std::promise be made from a non-POD object?

One of the things my app does is listen for and receive payloads from a socket. I never want to block. On each payload received, I want to create an object and pass it to a worker thread and forget about it until later which is how the prototype code works. But for the production code I want to reduce complexity (my app is large) by using the convenient async method. async takes a future made from a promise. For that to work I need to create a promise on my non-POD object represented below by the Xxx class. I don't see any way to do that (see error in my sample code below). Is it appropriate to use async here? If so, how can I construct a promise/future object that is more complex than int (all code examples I've see either use int or void):

#include <future>
class Xxx //non-POD object
{
  int i;
public:
  Xxx( int i ) : i( i ) {}
  int GetSquare() { return i * i; }
};

int factorial( std::future< Xxx > f )
{
  int res = 1;
  auto xxx = f.get();
  for( int i = xxx.GetSquare(); i > 1; i-- )
  {
    res *= i;
  }
  return res;
}

int _tmain( int argc, _TCHAR* argv[] )
{
  Xxx xxx( 2 ); // 2 represents one payload from the socket
  std::promise< Xxx > p; // error: no appropriate default constructor available
  std::future< Xxx > f = p.get_future();
  std::future< int > fu = std::async( factorial, std::move( f ) );
  p.set_value( xxx );
  fu.wait();
  return 0;
}
like image 404
rtischer8277 Avatar asked Mar 11 '15 16:03

rtischer8277


1 Answers

As Mike already answered, it's definitely a bug in the Visual C++ implementation of std::promise, what you're doing should work.

But I'm curious why you need to do it anyway. Maybe there's some other requirement that you've not shown to keep the example simple, but this would be the obvious way to write that code:

#include <future>

class Xxx //non-POD object
{
  int i;
public:
  Xxx( int i ) : i( i ) {}
  int GetSquare() { return i * i; }
};

int factorial( Xxx xxx )
{
  int res = 1;
  for( int i = xxx.GetSquare(); i > 1; i-- )
  {
    res *= i;
  }
  return res;
}

int main()
{
  Xxx xxx( 2 ); // 2 represents one payload from the socket
  std::future< int > fu = std::async( factorial, std::move( xxx ) );
  int fact = fu.get();
}
like image 160
Jonathan Wakely Avatar answered Sep 29 '22 00:09

Jonathan Wakely