clord
clord

Reputation: 338

Consume a std::future by connecting a QObject

I have some existing code that uses std::future/std::promise that I'd like to integrate with a Qt GUI cleanly.

Ideally, one could just:

std::future<int> future{do_something()};
connect(future, this, &MyObject::resultOfFuture);

and then implement resultOfFuture as a slot that gets one argument: the int value that came out of the std::future<int>. I've added this suggestion as a comment on QTBUG-50676. I like this best because most of my future/promises are not concurrent anyway, so I'd like to avoid firing up a thread just to wait on them. Also, type inference could then work between the future and the slot's parameter.

But it seems to me that this shouldn't be hard to implement using a wrapper Qt object (e.g., a version of QFutureWatcher that takes a std::future<int>). The two issues with a wrapper are:

  1. the wrapper will have to be concrete in its result type.
  2. the watcher would have to be concurrent in a thread?

Is there a best-practice to implement this sort of connection? Is there another way that can hook into the Qt main loop and avoid thread creation?

Upvotes: 2

Views: 544

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

std::future is missing continuations. The only way to turn the result of a std::future asynchronously into a function call delivering the result is to launch a thread watching it, and if you want to avoid busy-waiting you need one such thread per std::future, as there is no way to lazy-wait on multiple futures at once.

There are plans to create a future with continuation (a then operation), but they are not in C++ as of let alone .

You could write your own system of future/promise that mimics the interface of std::future and std::promise that does support continuations, or find a library that already did that.

A busy-wait solution that regularly checked if the future was ready could avoid launching a new thread.

In any case, std::experimental::then would make your problem trivial.

future.then( [some_state](auto future){
  try {
    auto x = future.get();
    // send message with x
  } catch( ... ) {
    // deal with exception
  }
} );

you can write your own std::experimetnal::future or find an implementation to use yourself, but this functionality cannot be provided without using an extra thread with a std::future.

Upvotes: 1

Related Questions