Merge Request #4 - October

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");