[libcamera-devel] [PATCH 10/19] libcamera: Define the threading model

Jacopo Mondi jacopo at jmondi.org
Mon Jan 20 15:18:44 CET 2020


Hi Laurent,

On Mon, Jan 20, 2020 at 02:24:28AM +0200, Laurent Pinchart wrote:
> 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 at ideasonboard.com>
> ---
>  Documentation/Doxyfile.in |  4 +-
>  src/libcamera/thread.cpp  | 82 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 85 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
> index 8e6fbdbb92b6..734672ed15dc 100644
> --- a/Documentation/Doxyfile.in
> +++ b/Documentation/Doxyfile.in
> @@ -239,7 +239,9 @@ TAB_SIZE               = 4
>  # 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.
>
> -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).
>  # A mapping has the form "name=value". For example adding "class=itcl::class"
> diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
> index fe32cd677596..c1698d469a6c 100644
> --- a/src/libcamera/thread.cpp
> +++ b/src/libcamera/thread.cpp
> @@ -19,6 +19,88 @@
>  #include "log.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-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.
> + *
> + * - \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 the function. This may deadlock and isn't allowed

s/the the/the

> + * 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.
> + *
> + * \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,
> + * an 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().

This is all good, but I would move this before the thread-safety
part..

Apart from that
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>

Thanks
  j

> + *
> + * \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 instance 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.
> + */
> +
>  /**
>   * \file thread.h
>   * \brief Thread support
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20200120/09b4140e/attachment.sig>


More information about the libcamera-devel mailing list