Merge Request #4 - October

On this page

Overview

This merge request adds strands and actors to make more optimized single threaded objects and reduce thread contention. It is recommended that services use the single-threaded mode.

Small Changes

  • PeriodicTask::start now does nothing when called from within the callback
  • Added qi::os::getEnvDefault to easily get an environment variable and cast it
  • Fixed random deadlock on Session::service
  • Added Application argument --qi-sdk-prefix and environment variable QI_SDK_PREFIX to specify where to find modules
  • Python: use sys.argv when no argument is provided to Application

New feature: Strands and Actors

You can now create a single-threaded objects by inheriting from Actor, all calls will then be queued (instead of blocked by a mutex). Remote calls, future continuations, signal callbacks, periodic tasks callbacks and async calls are guaranteed to be single-threaded.

For in-process communications, this guarantees that signal callbacks will be triggered in order.


            
             qi::Signal<int> sig;
sig.connect(&MyClass::myCallback, myObj);
sig(1);
sig(2);
// if MyClass is an actor, it is guaranteed that myCallback(1) will be called
// before myCallback(2)

            
           

Work is still in progress to support that for remote communications.

All this is also supported in Python if your object is single-threaded (the default), there is no need to inherit from anything.

It is recommended to write single-threaded services as thread contention is reduced by the framework in these cases. Furthermore, code do not need the use of synchronization primitives, which avoids a lot of bugs.

For further details, see qi::Strand and qi::Actor .

Deprecation: qi::async(Function, uint64_t)

The function qi::async(Function, uint64_t) is now deprecated. Use the alternatives which take a time point or a duration from qi clocks instead.


            
             template<typename R>
Future<R> async(boost::function<R()> callback, qi::Duration delay);
template<typename R>
Future<R> async(boost::function<R()> callback, qi::SteadyClockTimePoint timepoint);

qi::async(&myFunction); // schedule immediately
qi::async(&myFunction, qi::MilliSeconds(100));
qi::async(&myFunction, qi::steadyClockNow() + qi::MilliSeconds(100));

            
           

You can now bind arguments directly when using qi::async as you do when using Future::connect and others.


            
             qi::async(&myFunction, 42, "test");