[libcamera-devel] [PATCH v2 06/13] libcamera: Define the threading model

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Jan 22 21:57:16 CET 2020


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>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
Changes since v1:

- Move the thread-reentrancy after thread-objects and thread-signals
- Add a sentence that was mistakenly part of another patch
- Fix typos
---
 Documentation/Doxyfile.in |  4 +-
 src/libcamera/thread.cpp  | 84 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
index 1f746393568a..1c46b04b3f7e 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..38e01771111d 100644
--- a/src/libcamera/thread.cpp
+++ b/src/libcamera/thread.cpp
@@ -19,6 +19,90 @@
 #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-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
  * \brief Thread support
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list