Thread Support — kaa.base v0.6.0 documentation

### Navigation

- index
- next |
- previous |
- kaa.base v0.6.0 documentation »
- Asynchronous Programming »

# 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

  `active` | read-only | True 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_exit` | read/write | If True (default), wait for the thread on application exit.

  Signals

  `abort` | Emitted 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

  `abort` | Emitted 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.

### Navigation

- index
- next |
- previous |
- kaa.base v0.6.0 documentation »
- Asynchronous Programming »