libcamera: Define the threading model
Document the design of libcamera's threading support, and prepare to document thread-safety of classes and functions with a doxygen alias command. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
parent
8ce24bebbf
commit
fcfa11177f
2 changed files with 87 additions and 1 deletions
|
@ -239,7 +239,9 @@ TAB_SIZE = 4
|
||||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
# newlines (in the resulting output). You can put ^^ in the value part of an
|
||||||
# alias to insert a newline as if a physical newline was in the original file.
|
# alias to insert a newline as if a physical newline was in the original file.
|
||||||
|
|
||||||
ALIASES =
|
ALIASES = "context=\xrefitem context \"Thread Safety\" \"Thread Safety\""
|
||||||
|
ALIASES += "threadbound=\ref thread-bound \"thread-bound\""
|
||||||
|
ALIASES += "threadsafe=\ref thread-safe \"thread-safe\""
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||||
|
|
|
@ -19,6 +19,90 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \page thread Thread Support
|
||||||
|
*
|
||||||
|
* libcamera supports multi-threaded applications through a threading model that
|
||||||
|
* sets precise rules to guarantee thread-safe usage of the API. Additionally,
|
||||||
|
* libcamera makes internal use of threads, and offers APIs that simplify
|
||||||
|
* interactions with application threads. Careful compliance with the threading
|
||||||
|
* model will ensure avoidance of race conditions.
|
||||||
|
*
|
||||||
|
* \section thread-objects Threads and Objects
|
||||||
|
*
|
||||||
|
* Instances of the Object class and all its derived classes are thread-aware
|
||||||
|
* and are bound to the thread they are created in. They are said to *live* in
|
||||||
|
* a thread, and they interact with the event loop of their thread for the
|
||||||
|
* purpose of message passing and signal delivery. Messages posted to the
|
||||||
|
* object with Object::postMessage() will be delivered from the event loop of
|
||||||
|
* the thread that the object lives in. Signals delivered to the object, unless
|
||||||
|
* explicitly connected with ConnectionTypeDirect, will also be delivered from
|
||||||
|
* the object thread's event loop.
|
||||||
|
*
|
||||||
|
* All Object instances created by libcamera are bound to an internal thread,
|
||||||
|
* and applications don't need to provide an event loop to support them. Object
|
||||||
|
* instances created by applications require an event loop. It is the
|
||||||
|
* responsibility of applications to provide that event loop, either explicitly
|
||||||
|
* through CameraManager::setEventDispatcher(), or by running the default event
|
||||||
|
* loop provided by CameraManager::eventDispatcher() in their main thread. The
|
||||||
|
* main thread of an application is the one that calls CameraManager::start().
|
||||||
|
*
|
||||||
|
* \section thread-signals Threads and Signals
|
||||||
|
*
|
||||||
|
* When sent to a receiver that does not inherit from the Object class, signals
|
||||||
|
* are delivered synchronously in the thread of the sender. When the receiver
|
||||||
|
* inherits from the Object class, delivery is by default asynchronous if the
|
||||||
|
* sender and receiver live in different threads. In that case, the signal is
|
||||||
|
* posted to the receiver's message queue and will be delivered from the
|
||||||
|
* receiver's event loop, running in the receiver's thread. This mechanism can
|
||||||
|
* be overridden by selecting a different connection type when calling
|
||||||
|
* Signal::connect().
|
||||||
|
*
|
||||||
|
* Asynchronous signal delivery is used internally in libcamera, but is also
|
||||||
|
* available to applications if desired. To use this feature, applications
|
||||||
|
* shall create receiver classes that inherit from the Object class, and
|
||||||
|
* provide an event loop to the CameraManager as explained above. Note that
|
||||||
|
* Object instances created by the application are limited to living in the
|
||||||
|
* application's main thread. Creating Object instances from another thread of
|
||||||
|
* an application causes undefined behaviour.
|
||||||
|
*
|
||||||
|
* \section thread-reentrancy Reentrancy and Thread-Safety
|
||||||
|
*
|
||||||
|
* Through the documentation, several terms are used to define how classes and
|
||||||
|
* their member functions can be used from multiple threads.
|
||||||
|
*
|
||||||
|
* - A **reentrant** function may be called simultaneously from multiple
|
||||||
|
* threads if and only if each invocation uses a different instance of the
|
||||||
|
* class. This is the default for all member functions not explictly marked
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* - \anchor thread-safe A **thread-safe** function may be called
|
||||||
|
* simultaneously from multiple threads on the same instance of a class. A
|
||||||
|
* thread-safe function is thus reentrant. Thread-safe functions may also be
|
||||||
|
* called simultaneously with any other reentrant function of the same class
|
||||||
|
* on the same instance.
|
||||||
|
*
|
||||||
|
* - \anchor thread-bound A **thread-bound** function may be called only from
|
||||||
|
* the thread that the class instances lives in (see section \ref
|
||||||
|
* thread-objects). For instances of classes that do not derive from the
|
||||||
|
* Object class, this is the thread in which the instance was created. A
|
||||||
|
* thread-bound function is not thread-safe, and may or may not be reentrant.
|
||||||
|
*
|
||||||
|
* Neither reentrancy nor thread-safety, in this context, mean that a function
|
||||||
|
* may be called simultaneously from the same thread, for instance from a
|
||||||
|
* callback invoked by the function. This may deadlock and isn't allowed unless
|
||||||
|
* separately documented.
|
||||||
|
*
|
||||||
|
* A class is defined as reentrant, thread-safe or thread-bound if all its
|
||||||
|
* member functions are reentrant, thread-safe or thread-bound respectively.
|
||||||
|
* Some member functions may additionally be documented as having additional
|
||||||
|
* thread-related attributes.
|
||||||
|
*
|
||||||
|
* Most classes are reentrant but not thread-safe, as making them fully
|
||||||
|
* thread-safe would incur locking costs considered prohibitive for the
|
||||||
|
* expected use cases.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file thread.h
|
* \file thread.h
|
||||||
* \brief Thread support
|
* \brief Thread support
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue