Thread Support

The threaded decorator

Any function or method may be decorated with @kaa.threaded() which takes two optional arguments: a thread name, and a priority. If a thread name is specified, the decorated function is wrapped in NamedThreadCallback, and invocations of that function are queued to be executed in a single thread. If the thread name is kaa.MAINTHREAD the decorated function is invoked from the main thread. If no thread name is specified, the function is wrapped in ThreadCallback so that each invocation is executed in a separate thread. Because these callbacks returns ThreadInProgress objects, which are derived from InProgress, they may be yielded from coroutines.

For example:

@kaa.threaded()
def do_blocking_task():
   [...]
   return 42

@kaa.coroutine()
def do_something_else():
   try:
      result = yield do_blocking_task()
   except:
      print "Exception raised in thread"

   print "Thread returned", result

The threaded decorator also supports a async kwarg, which is by default True. When True, the decorated function returns a ThreadInProgress object. When False, however, invocation of the function blocks until the decorated function completes, and its return value is passed back. Internally, the decorator merely invokes wait() on the InProgress returned by the threaded function, which means the main loop is otherwise kept alive for timers and I/O handlers. This allows a threaded function to be used as a standard callback (but in practice it is not used often).

kaa.threaded(name=None, priority=0, async=True, progress=False)

The decorator makes sure the function is always called in the thread with the given name. The function will return an InProgress object if async=True (default), otherwise it will cause invoking the decorated function to block (the main loop is kept alive) and its result is returned. If progress is True, the first argument to the function is an InProgressStatus object to return execution progress.

If name=kaa.MAINTHREAD, the decorated function will be invoked from the main thread. (In this case, currently the priority kwarg is ignored.)

As a rule of thumb, if you have a function that must always be called in the main thread, you would use @kaa.threaded(kaa.MAINTHREAD) as mentioned above. If you need to decide case-by-case, don’t decorate it and use MainThreadCallback when needed.

The synchronized decorator

class kaa.synchronized(obj=None)

synchronized decorator and with statement similar to synchronized in Java. When decorating a non-member function, a lock or any class inheriting from object may be provided.

Parameters:
  • obj – object were all calls should be synchronized to. if not provided it will be the object for member functions or an RLock for functions.

Create a synchronized object. Note: when used on classes a new member _kaa_synchronized_lock will be added to that class.

Some functions may need to block concurrent access to certain data structures, or prevent concurrent entry to the whole function. In these cases, kaa.synchronized can be used, which serves as both a decorator as well as a context manager for use with Python’s with statement:

class Test(object):

    def foo(self):
        # call to do_something() can be done concurrently by other threads.
        do_something()
        with kaa.synchronized(self):
            # Anything in this block however is synchronized between threads.
            do_something_else()


    # bar() is a protected function
    @kaa.synchronized()
    def bar(self, x, y):
        do_something_else()

The decorator will synchronize on the actual object. Two different objects can access the same function in two threads. On the other hand it is not possible that one thread is in the protected block of foo and another one calling bar.

The decorator can also be used for functions outside a class. In that case the decorator only protects this one function. If more functions should be protected against each other, a Python RLock object can be provided:

# threading.Lock does NOT work
lock = threading.RLock()

@kaa.synchronized(lock)
def foo():
    # foo and bar synchronized
    do_something()

@kaa.synchronized(lock)
def bar(x):
    # foo and bar synchronized
    do_something()

@kaa.synchronized()
def baz():
    # only_baz_synchronized
    do_something()

The following thread-related functions are available:

kaa.is_mainthread()

Return True if the current thread is the main thread.

Note that the “main thread” is considered to be the thread in which the kaa main loop is running. This is usually, but not necessarily, what Python considers to be the main thread. (If you call kaa.main.run() in the main Python thread, then they are equivalent.)

kaa.main.wakeup()
Wake up main thread. A thread can use this function to wake up a mainloop waiting on a select.

Callback Classes for Threads

Kaa provides a ThreadCallback class which can be used to invoke a callback in a new thread every time the ThreadCallback object is invoked.

With the NamedThreadCallback class, invocations are queued and each executed in the same thread. A priority may also be specified, and NamedThreadCallback objects with the highest priority is first in the queue (and hence executed first). This allows you to create a priority-based job queue that executes asynchronously.

Instances of the two classes above are callable, and they return ThreadInProgress objects:

def handle_result(result):
   print "Thread returned with", result

kaa.ThreadCallback(do_blocking_task)(arg1, arg2).connect(handle_result)

class kaa.ThreadInProgress(callback, *args, **kwargs)

Synopsis

Class Hierarchy

kaa.Signal
kaa.Object
└─ kaa.InProgress
     └─ kaa.ThreadInProgress

Methods
abort()Aborts the callback being executed inside a thread. (Or attempts to.)
Properties
activeread-onlyTrue if the callback is still waiting to be processed.
Signals
This class has no signals.

Methods

abort(exc=None)

Aborts the callback being executed inside a thread. (Or attempts to.)

Invocation of a ThreadCallback or NamedThreadCallback will return a ThreadInProgress object which may be aborted by calling this method. When an in-progress thread is aborted, an InProgressAborted exception is raised inside the thread.

Just prior to raising InProgressAborted inside the thread, the abort signal will be emitted. Callbacks connected to this signal are invoked within the thread from which abort() was called. If any of the callbacks return False, InProgressAborted will not be raised in the thread.

It is possible to catch InProgressAborted within the thread to deal with cleanup, but any return value from the threaded callback will be discarded. It is therefore not possible abort an abort. However, if the InProgress is aborted before the thread has a chance to start, the thread is not started at all, and so obviously the threaded callback will not receive InProgressAborted.

Warning

This method raises an exception asynchronously within the thread, and this is unreliable. The asynchronous exception may get inadvertently cleared internally, and if it doesn’t, it will in any case take up to 100 bytecodes for it to trigger within the thread. This approach still has uses as a general-purposes aborting mechanism, but, if possible, it is preferable for you to implement custom logic by attaching an abort handler to the ThreadCallback or NamedThreadCallback object.

Properties

active
True if the callback is still waiting to be processed.

class kaa.ThreadCallback(callback, *args, **kwargs)

Notifier aware wrapper for threads. When a thread is started, it is impossible to fork the current process into a second one without exec both using the main loop because of the shared _thread_notifier_pipe.

Parameters:
  • callback – callable function or object
  • args – arguments for the callback
  • kwargs – keyword arguments for the callback

Synopsis

Class Hierarchy

kaa.Object
kaa.Callback
└─ kaa.thread.ThreadCallbackBase
     └─ kaa.ThreadCallback

Methods
This class has no methods.
Properties
wait_on_exitread/writeIf True (default), wait for the thread on application exit.
Signals
abortEmitted when the thread callback is aborted.

Properties

wait_on_exit
If True (default), wait for the thread on application exit.

Signals

abort

Emitted when the thread callback is aborted.

def callback()
This callback takes no arguments

See abort() for a more detailed discussion.

Handlers may return False to prevent InProgressAborted from being raised inside the thread. However, the ThreadInProgress is still considered aborted regardless. Handlers of this signal are intended to implement more appropriate logic to cancel the threaded callback.

class kaa.NamedThreadCallback(thread_information, func, *args, **kwargs)

A callback to run a function in a thread. This class is used by the threaded decorator, but it is also possible to use this call directly.

Synopsis

Class Hierarchy

kaa.Object
kaa.Callback
└─ kaa.thread.ThreadCallbackBase
     └─ kaa.NamedThreadCallback

Methods
This class has no methods.
Properties
This class has no properties.
Signals
abortEmitted when the thread callback is aborted.

Signals

abort

Emitted when the thread callback is aborted.

def callback()
This callback takes no arguments

See abort() for a more detailed discussion.

Handlers may return False to prevent InProgressAborted from being raised inside the thread. However, the ThreadInProgress is still considered aborted regardless. Handlers of this signal are intended to implement more appropriate logic to cancel the threaded callback.

The MainThreadCallback is a callback that will be executed from the main loop. The thread calling this function will return immediately after calling the object without waiting for the result. Invoking MainThreadCallbacks always returns an InProgress object:

def needs_to_be_called_from_main(param):
    print param
    return 5

# ... suppose we are in a thread here ...
cb = kaa.MainThreadCallback(needs_to_be_called_from_main)
print cb(3).wait()

class kaa.MainThreadCallback(callback, *args, **kwargs)

Callback that is invoked from the main thread.

Parameters:
  • callback – callable function or object
  • args – arguments for the callback
  • kwargs – keyword arguments for the callback

Synopsis

Class Hierarchy

kaa.Callback
└─ kaa.MainThreadCallback

Methods
This class has no methods.
Properties
This class has no properties.
Signals
This class has no signals.