Aldebaran documentation What's new in NAOqi 2.4.3?

qi::Actor and qi::Strand

A Strand allows one to schedule asynchronous work with the guarantee that two tasks will never be executed in parallel. This is useful to avoid data races, mutexes, and deadlocks.

An Actor receives messages and processes them. Basically, it’s just an object containing a Strand so that all asynchronous work it receives will be executed sequentially.


Global Classes

Detailed Description

Strand Usage

A Strand works exactly as an event loop:

#include <qi/strand.hpp>

qi::Strand strand(*qi::getEventLoop());
qi::Future<void> future = strand.async(myfunction, qi::MilliSeconds(100));
// you can now cancel future
// and/or wait for it

A strand’s destructor will block until all work scheduled is finished or cancelled. You must not schedule any work when the strand is being destroyed.

The event loop must not be destroyed before all strands associated to it are destroyed.

Actor Usage

You can make a single threaded object by inheriting from Actor. All work scheduled on that object will be executed on a single thread so that there will never be more than one call in parallel.

#include <qi/actor.hpp>

class MyActor : public Actor
  void myFunction(const std::string& str);

// works with type-erasure
QI_REGISTER_OBJECT(MyActor, myFunction);
// works with futures
future.connect(&MyActor::myFunction, myActor, "my string");
// works with signals
signal.connect(&MyActor::myFunction, myActor, _1);
// works with type-erased signal/property connections
// (work is in progress to simplify the syntax)
myObject.connect("mySignal", myActor.strand()->schedulerFor<void(std::string)>(&MyActor::myFunction, myActor, _1));
// works with periodic tasks
periodicTask.setCallback(&MyActor::myFunction, myActor, _1);
// works with async calls
qi::async(&MyActor::myFunction, myActor, "my string", qi::Seconds(1));


When connecting your object, do not use bind functions. This code does not provide single threaded guarantees:

// *NOT* single threaded
future.connect(boost::bind(&MyActor::myFunction, myActor, "my string"));

Calling the object directly does not provide these guarantees either:

// *NOT* single threaded
myActor.myFunction("my string");

Same thing when scheduling directly on the main eventloop.

// *NOT* single threaded
qi::getEventLoop()->async(boost::bind(&MyActor::myFunction, myActor,
    "my string"));

It is possible to inherit both from Actor and Trackable as an Actor is not Trackable by default.


qi::Strand Class Reference



#include <qi/strand.hpp>
  • Inherits: noncopyable, qi::ExecutionContext

Public Functions

Strand(qi::ExecutionContext& executionContext)
void post(const boost::function<void()>& callback)
qi::Future<void> async(const boost::function<void()>& cb, qi::SteadyClockTimePoint tp)
qi::Future<void> async(const boost::function<void()>& cb, qi::Duration delay)
bool isInThisContext()

Detailed Description

Class that schedules tasks sequentially

A strand allows one to schedule work on an eventloop with the guaranty that two callback will never be called concurrently.

Methods are thread-safe except for destructor which must never be called concurrently.

Function Documentation


Construct a strand that will schedule work on the default event loop.

qi::Strand::Strand(qi::ExecutionContext& executionContext)

Construct a strand that will schedule work on executionContext.


Destroys the strand

This will wait for all scheduled tasks to finish

void qi::Strand::post(const boost::function<void()>& callback)

post a callback to be executed as soon as possible

qi::Future<void> qi::Strand::async(const boost::function<void()>& cb, qi::SteadyClockTimePoint tp)

call a callback asynchronously to be executed on tp

qi::Future<void> qi::Strand::async(const boost::function<void()>& cb, qi::Duration delay = qi::Duration(0)

call a callback asynchronously to be executed in delay

bool qi::Strand::isInThisContext()

return true if the current thread is in this context

qi::Actor Class Reference



#include <qi/actor.hpp>

Public Functions

Actor(const Actor&)
Actor(qi::ExecutionContext& ec)
qi::Strand* strand() const

Detailed Description

Class that represents an actor.

Inherit from this class if you want your class to be an actor (as in the actor model). This means that your class will receive “messages” and not be called. In other words, there will never be to calls to your object in parallel, they will be queued.

Function Documentation

qi::Actor::Actor(const Actor&)
qi::Actor::Actor(qi::ExecutionContext& ec)
qi::Strand* qi::Actor::strand() const