Asynchronous operations

Introduction

libqi provides a threadpool for doing small asynchronous operations. Note that blocking in these threads impacts the whole system as a non-working thread will prevent other work from being scheduled.

With C++ functions

You can push a task to be executed asynchronously from a simple C++ function. It is also possible to specify a delay for the task.


            
             #include <qi/application.hpp>
#include <qi/eventloop.hpp>

void doSomething(int value) {
  std::cout << "value is " << value << std::endl;
}

int main(int argc, char* argv[]) {
  qi::Application app(argc, argv);

  // run as soon as possible
  qi::Future<void> future = qi::async(boost::bind(doSomething, 42));
  // run in 2 seconds
  qi::Future<void> future2 = qi::async(boost::bind(doSomething, 42), 2000000);

  // do stuff...

  future.wait();
  future2.wait();

  return 0;
}

            
           

If your function should be called periodically, use qi::PeriodicTask .

It is also possible to cancel the execution of a task if it hasn’t started yet:


            
             qi::Future<void> future = qi::async(boost::bind(doSomething, 42), 2000000);

future.cancel();

// doSomething will never be called

            
           

With a qi::AnyObject

There are two ways of using an AnyObject asynchronously, with the async() method and the qi::async() function.


            
             qi::AnyObject tts = session.service("ALTextToSpeech");
qi::AnyObject motion = session.service("ALMotion");
qi::Future<void> sayOp = qi::async(tts, "say", "This is a very very very very long sentence.");
qi::Future<void> moveOp = motion.async("moveTo", 1, 0, 0);
// Wait for both operations to terminate.
sayOp.wait();
moveOp.wait();

            
           

There is another way of doing async with AnyObjects:


            
             tts.post("say", "Yes!");

            
           

post() does not return a future, it just posts a call and discards the return value. This is close to calling async() but is a bit faster (and spare a message when using remote sessions) because no future is created and the return value is discarded very early. Use it whenever you can when you don’t need the future from async .

Using the returned future

Look at the qi::Future for more complete documentation, but here is what you most definitely need to know:

  • If the method throws an exception, it is stored in the Future , and can be accessed using error() .
  • Use wait() to wait for the future to complete. It can accept a timeout duration as argument, and will return the state of the future.
  • Use value() and error() to get the stored value or error.
  • You can register a callback to be notified when the future finishes with qi::Future::connect() .

With a qi::Future

The callbacks connected to the qi::Future will also be called from the threadpool.


            
             void callback() {
  std::cout << "I'm called from a thread" << std::endl;
}

qi::Promise<void> promise;
qi::Future<void> future = promise.future();
future.connect(callback);
promise.setValue(0);