[libcamera-devel,v2,3/5] Documentation: Add Thread support page
diff mbox series

Message ID 20240105164104.78398-4-dan.scally@ideasonboard.com
State Superseded
Headers show
Series
  • Improve libcamera documentation
Related show

Commit Message

Dan Scally Jan. 5, 2024, 4:41 p.m. UTC
Move the Thread Support page and the section of the Thread class'
documentation dealing with stopping threads from
src/libcamera/base/thread.cpp to a dedicated .dox file at
Documentation/. This is done to support the splitting of the
Documentation into a public and internal version. With a separate
page, references can be made to thread safety without having to
include the Thread class in the doxygen run.

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
---
Changes in v2:

	- New patch

 Documentation/Doxyfile.in     |   6 +-
 Documentation/thread.dox      | 122 +++++++++++++++++++++++++++++++++
 src/libcamera/base/thread.cpp | 123 ----------------------------------
 3 files changed, 126 insertions(+), 125 deletions(-)
 create mode 100644 Documentation/thread.dox

Comments

Jacopo Mondi Jan. 9, 2024, 2:06 p.m. UTC | #1
Hi Dan

On Fri, Jan 05, 2024 at 04:41:02PM +0000, Daniel Scally via libcamera-devel wrote:
> Move the Thread Support page and the section of the Thread class'
> documentation dealing with stopping threads from
> src/libcamera/base/thread.cpp to a dedicated .dox file at
> Documentation/. This is done to support the splitting of the
> Documentation into a public and internal version. With a separate
> page, references can be made to thread safety without having to
> include the Thread class in the doxygen run.
>
> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>

Looks good!

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

> ---
> Changes in v2:
>
> 	- New patch
>
>  Documentation/Doxyfile.in     |   6 +-
>  Documentation/thread.dox      | 122 +++++++++++++++++++++++++++++++++
>  src/libcamera/base/thread.cpp | 123 ----------------------------------
>  3 files changed, 126 insertions(+), 125 deletions(-)
>  create mode 100644 Documentation/thread.dox
>
> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
> index a86ea6c1..48fea8bc 100644
> --- a/Documentation/Doxyfile.in
> +++ b/Documentation/Doxyfile.in
> @@ -21,7 +21,8 @@ CASE_SENSE_NAMES       = YES
>
>  QUIET                  = YES
>
> -INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
> +INPUT                  = "@TOP_SRCDIR@/Documentation" \
> +                         "@TOP_SRCDIR@/include/libcamera" \
>                           "@TOP_SRCDIR@/src/ipa/ipu3" \
>                           "@TOP_SRCDIR@/src/ipa/libipa" \
>                           "@TOP_SRCDIR@/src/libcamera" \
> @@ -30,7 +31,8 @@ INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
>
>  FILE_PATTERNS          = *.c \
>                           *.cpp \
> -                         *.h
> +                         *.h \
> +			 *.dox
>
>  RECURSIVE              = YES
>
> diff --git a/Documentation/thread.dox b/Documentation/thread.dox
> new file mode 100644
> index 00000000..805a864e
> --- /dev/null
> +++ b/Documentation/thread.dox
> @@ -0,0 +1,122 @@
> +/**
> + * \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.
> + *
> + * Every thread created by libcamera is associated with an instance of the
> + * Thread class. Those threads run an internal event loop by default to
> + * dispatch events to objects. Additionally, the main thread of the application
> + * (defined as the thread that calls CameraManager::start()) is also associated
> + * with a Thread instance, but has no event loop accessible to libcamera. Other
> + * application threads are not visible to libcamera.
> + *
> + * \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 internally by libcamera are bound to internal
> + * threads. As objects interact with thread event loops for proper operation,
> + * creating an Object instance in a thread that has no internal event loop (such
> + * as the main application thread, or libcamera threads that have a custom main
> + * loop), prevents some features of the Object class from being used. See
> + * Thread::exec() for more details.
> + *
> + * \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().
> + *
> + * \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.
> + *
> + * \section thread-stop Stopping Threads
> + *
> + * Threads can't be forcibly stopped. Instead, a thread user first requests the
> + * thread to exit and then waits for the thread's main function to react to the
> + * request and return, at which points the thread will stop.
> + *
> + * For threads running exec(), the exit() function is used to request the thread
> + * to exit. For threads subclassing the Thread class and implementing a custom
> + * run() function, a subclass-specific mechanism shall be provided. In either
> + * case, the wait() function shall be called to wait for the thread to stop.
> + *
> + * Due to their asynchronous nature, threads are subject to race conditions when
> + * they stop. This is of particular importance for messages posted to the thread
> + * with postMessage() (and the other mechanisms that rely on it, such as
> + * Object::invokeMethod() or asynchronous signal delivery). To understand the
> + * issues, three contexts need to be considered:
> + *
> + * - The worker is the Thread performing work and being instructed to stop.
> + * - The controller is the context which instructs the worker thread to stop.
> + * - The other contexts are any threads other than the worker and controller
> + *   that interact with the worker thread.
> + *
> + * Messages posted to the worker thread from the controller context before
> + * calling exit() are queued to the thread's message queue, and the Thread class
> + * offers no guarantee that those messages will be processed before the thread
> + * stops. This allows threads to stop fast.
> + *
> + * A thread that requires delivery of messages posted from the controller
> + * context before exit() should reimplement the run() function and call
> + * dispatchMessages() after exec().
> + *
> + * Messages posted to the worker thread from the other contexts are asynchronous
> + * with respect to the exit() call from the controller context. There is no
> + * guarantee as to whether those messages will be processed or not before the
> + * thread stops.
> + *
> + * Messages that are not processed will stay in the queue, in the exact same way
> + * as messages posted after the thread has stopped. They will be processed when
> + * the thread is restarted. If the thread is never restarted, they will be
> + * deleted without being processed when the Thread instance is destroyed.
> + */
> diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
> index b96951ac..6b034e06 100644
> --- a/src/libcamera/base/thread.cpp
> +++ b/src/libcamera/base/thread.cpp
> @@ -19,88 +19,6 @@
>  #include <libcamera/base/message.h>
>  #include <libcamera/base/mutex.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.
> - *
> - * Every thread created by libcamera is associated with an instance of the
> - * Thread class. Those threads run an internal event loop by default to
> - * dispatch events to objects. Additionally, the main thread of the application
> - * (defined as the thread that calls CameraManager::start()) is also associated
> - * with a Thread instance, but has no event loop accessible to libcamera. Other
> - * application threads are not visible to libcamera.
> - *
> - * \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 internally by libcamera are bound to internal
> - * threads. As objects interact with thread event loops for proper operation,
> - * creating an Object instance in a thread that has no internal event loop (such
> - * as the main application thread, or libcamera threads that have a custom main
> - * loop), prevents some features of the Object class from being used. See
> - * Thread::exec() for more details.
> - *
> - * \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().
> - *
> - * \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 base/thread.h
>   * \brief Thread support
> @@ -216,47 +134,6 @@ ThreadData *ThreadData::current()
>   * called. The event loop dispatches events (messages, notifiers and timers)
>   * sent to the objects living in the thread. This behaviour can be modified by
>   * overriding the run() function.
> - *
> - * \section thread-stop Stopping Threads
> - *
> - * Threads can't be forcibly stopped. Instead, a thread user first requests the
> - * thread to exit and then waits for the thread's main function to react to the
> - * request and return, at which points the thread will stop.
> - *
> - * For threads running exec(), the exit() function is used to request the thread
> - * to exit. For threads subclassing the Thread class and implementing a custom
> - * run() function, a subclass-specific mechanism shall be provided. In either
> - * case, the wait() function shall be called to wait for the thread to stop.
> - *
> - * Due to their asynchronous nature, threads are subject to race conditions when
> - * they stop. This is of particular importance for messages posted to the thread
> - * with postMessage() (and the other mechanisms that rely on it, such as
> - * Object::invokeMethod() or asynchronous signal delivery). To understand the
> - * issues, three contexts need to be considered:
> - *
> - * - The worker is the Thread performing work and being instructed to stop.
> - * - The controller is the context which instructs the worker thread to stop.
> - * - The other contexts are any threads other than the worker and controller
> - *   that interact with the worker thread.
> - *
> - * Messages posted to the worker thread from the controller context before
> - * calling exit() are queued to the thread's message queue, and the Thread class
> - * offers no guarantee that those messages will be processed before the thread
> - * stops. This allows threads to stop fast.
> - *
> - * A thread that requires delivery of messages posted from the controller
> - * context before exit() should reimplement the run() function and call
> - * dispatchMessages() after exec().
> - *
> - * Messages posted to the worker thread from the other contexts are asynchronous
> - * with respect to the exit() call from the controller context. There is no
> - * guarantee as to whether those messages will be processed or not before the
> - * thread stops.
> - *
> - * Messages that are not processed will stay in the queue, in the exact same way
> - * as messages posted after the thread has stopped. They will be processed when
> - * the thread is restarted. If the thread is never restarted, they will be
> - * deleted without being processed when the Thread instance is destroyed.
>   */
>
>  /**
> --
> 2.34.1
>
Kieran Bingham Jan. 9, 2024, 6:09 p.m. UTC | #2
Quoting Daniel Scally via libcamera-devel (2024-01-05 16:41:02)
> Move the Thread Support page and the section of the Thread class'
> documentation dealing with stopping threads from
> src/libcamera/base/thread.cpp to a dedicated .dox file at
> Documentation/. This is done to support the splitting of the
> Documentation into a public and internal version. With a separate
> page, references can be made to thread safety without having to
> include the Thread class in the doxygen run.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> 
> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> ---
> Changes in v2:
> 
>         - New patch
> 
>  Documentation/Doxyfile.in     |   6 +-
>  Documentation/thread.dox      | 122 +++++++++++++++++++++++++++++++++
>  src/libcamera/base/thread.cpp | 123 ----------------------------------
>  3 files changed, 126 insertions(+), 125 deletions(-)
>  create mode 100644 Documentation/thread.dox
> 
> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
> index a86ea6c1..48fea8bc 100644
> --- a/Documentation/Doxyfile.in
> +++ b/Documentation/Doxyfile.in
> @@ -21,7 +21,8 @@ CASE_SENSE_NAMES       = YES
>  
>  QUIET                  = YES
>  
> -INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
> +INPUT                  = "@TOP_SRCDIR@/Documentation" \
> +                         "@TOP_SRCDIR@/include/libcamera" \
>                           "@TOP_SRCDIR@/src/ipa/ipu3" \
>                           "@TOP_SRCDIR@/src/ipa/libipa" \
>                           "@TOP_SRCDIR@/src/libcamera" \
> @@ -30,7 +31,8 @@ INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
>  
>  FILE_PATTERNS          = *.c \
>                           *.cpp \
> -                         *.h
> +                         *.h \
> +                        *.dox
>  
>  RECURSIVE              = YES
>  
> diff --git a/Documentation/thread.dox b/Documentation/thread.dox
> new file mode 100644
> index 00000000..805a864e
> --- /dev/null
> +++ b/Documentation/thread.dox
> @@ -0,0 +1,122 @@
> +/**
> + * \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.
> + *
> + * Every thread created by libcamera is associated with an instance of the
> + * Thread class. Those threads run an internal event loop by default to
> + * dispatch events to objects. Additionally, the main thread of the application
> + * (defined as the thread that calls CameraManager::start()) is also associated
> + * with a Thread instance, but has no event loop accessible to libcamera. Other
> + * application threads are not visible to libcamera.
> + *
> + * \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 internally by libcamera are bound to internal
> + * threads. As objects interact with thread event loops for proper operation,
> + * creating an Object instance in a thread that has no internal event loop (such
> + * as the main application thread, or libcamera threads that have a custom main
> + * loop), prevents some features of the Object class from being used. See
> + * Thread::exec() for more details.
> + *
> + * \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().
> + *
> + * \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.
> + *
> + * \section thread-stop Stopping Threads
> + *
> + * Threads can't be forcibly stopped. Instead, a thread user first requests the
> + * thread to exit and then waits for the thread's main function to react to the
> + * request and return, at which points the thread will stop.
> + *
> + * For threads running exec(), the exit() function is used to request the thread
> + * to exit. For threads subclassing the Thread class and implementing a custom
> + * run() function, a subclass-specific mechanism shall be provided. In either
> + * case, the wait() function shall be called to wait for the thread to stop.
> + *
> + * Due to their asynchronous nature, threads are subject to race conditions when
> + * they stop. This is of particular importance for messages posted to the thread
> + * with postMessage() (and the other mechanisms that rely on it, such as
> + * Object::invokeMethod() or asynchronous signal delivery). To understand the
> + * issues, three contexts need to be considered:
> + *
> + * - The worker is the Thread performing work and being instructed to stop.
> + * - The controller is the context which instructs the worker thread to stop.
> + * - The other contexts are any threads other than the worker and controller
> + *   that interact with the worker thread.
> + *
> + * Messages posted to the worker thread from the controller context before
> + * calling exit() are queued to the thread's message queue, and the Thread class
> + * offers no guarantee that those messages will be processed before the thread
> + * stops. This allows threads to stop fast.
> + *
> + * A thread that requires delivery of messages posted from the controller
> + * context before exit() should reimplement the run() function and call
> + * dispatchMessages() after exec().
> + *
> + * Messages posted to the worker thread from the other contexts are asynchronous
> + * with respect to the exit() call from the controller context. There is no
> + * guarantee as to whether those messages will be processed or not before the
> + * thread stops.
> + *
> + * Messages that are not processed will stay in the queue, in the exact same way
> + * as messages posted after the thread has stopped. They will be processed when
> + * the thread is restarted. If the thread is never restarted, they will be
> + * deleted without being processed when the Thread instance is destroyed.
> + */
> diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
> index b96951ac..6b034e06 100644
> --- a/src/libcamera/base/thread.cpp
> +++ b/src/libcamera/base/thread.cpp
> @@ -19,88 +19,6 @@
>  #include <libcamera/base/message.h>
>  #include <libcamera/base/mutex.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.
> - *
> - * Every thread created by libcamera is associated with an instance of the
> - * Thread class. Those threads run an internal event loop by default to
> - * dispatch events to objects. Additionally, the main thread of the application
> - * (defined as the thread that calls CameraManager::start()) is also associated
> - * with a Thread instance, but has no event loop accessible to libcamera. Other
> - * application threads are not visible to libcamera.
> - *
> - * \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 internally by libcamera are bound to internal
> - * threads. As objects interact with thread event loops for proper operation,
> - * creating an Object instance in a thread that has no internal event loop (such
> - * as the main application thread, or libcamera threads that have a custom main
> - * loop), prevents some features of the Object class from being used. See
> - * Thread::exec() for more details.
> - *
> - * \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().
> - *
> - * \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 base/thread.h
>   * \brief Thread support
> @@ -216,47 +134,6 @@ ThreadData *ThreadData::current()
>   * called. The event loop dispatches events (messages, notifiers and timers)
>   * sent to the objects living in the thread. This behaviour can be modified by
>   * overriding the run() function.
> - *
> - * \section thread-stop Stopping Threads
> - *
> - * Threads can't be forcibly stopped. Instead, a thread user first requests the
> - * thread to exit and then waits for the thread's main function to react to the
> - * request and return, at which points the thread will stop.
> - *
> - * For threads running exec(), the exit() function is used to request the thread
> - * to exit. For threads subclassing the Thread class and implementing a custom
> - * run() function, a subclass-specific mechanism shall be provided. In either
> - * case, the wait() function shall be called to wait for the thread to stop.
> - *
> - * Due to their asynchronous nature, threads are subject to race conditions when
> - * they stop. This is of particular importance for messages posted to the thread
> - * with postMessage() (and the other mechanisms that rely on it, such as
> - * Object::invokeMethod() or asynchronous signal delivery). To understand the
> - * issues, three contexts need to be considered:
> - *
> - * - The worker is the Thread performing work and being instructed to stop.
> - * - The controller is the context which instructs the worker thread to stop.
> - * - The other contexts are any threads other than the worker and controller
> - *   that interact with the worker thread.
> - *
> - * Messages posted to the worker thread from the controller context before
> - * calling exit() are queued to the thread's message queue, and the Thread class
> - * offers no guarantee that those messages will be processed before the thread
> - * stops. This allows threads to stop fast.
> - *
> - * A thread that requires delivery of messages posted from the controller
> - * context before exit() should reimplement the run() function and call
> - * dispatchMessages() after exec().
> - *
> - * Messages posted to the worker thread from the other contexts are asynchronous
> - * with respect to the exit() call from the controller context. There is no
> - * guarantee as to whether those messages will be processed or not before the
> - * thread stops.
> - *
> - * Messages that are not processed will stay in the queue, in the exact same way
> - * as messages posted after the thread has stopped. They will be processed when
> - * the thread is restarted. If the thread is never restarted, they will be
> - * deleted without being processed when the Thread instance is destroyed.
>   */
>  
>  /**
> -- 
> 2.34.1
>

Patch
diff mbox series

diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
index a86ea6c1..48fea8bc 100644
--- a/Documentation/Doxyfile.in
+++ b/Documentation/Doxyfile.in
@@ -21,7 +21,8 @@  CASE_SENSE_NAMES       = YES
 
 QUIET                  = YES
 
-INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
+INPUT                  = "@TOP_SRCDIR@/Documentation" \
+                         "@TOP_SRCDIR@/include/libcamera" \
                          "@TOP_SRCDIR@/src/ipa/ipu3" \
                          "@TOP_SRCDIR@/src/ipa/libipa" \
                          "@TOP_SRCDIR@/src/libcamera" \
@@ -30,7 +31,8 @@  INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
 
 FILE_PATTERNS          = *.c \
                          *.cpp \
-                         *.h
+                         *.h \
+			 *.dox
 
 RECURSIVE              = YES
 
diff --git a/Documentation/thread.dox b/Documentation/thread.dox
new file mode 100644
index 00000000..805a864e
--- /dev/null
+++ b/Documentation/thread.dox
@@ -0,0 +1,122 @@ 
+/**
+ * \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.
+ *
+ * Every thread created by libcamera is associated with an instance of the
+ * Thread class. Those threads run an internal event loop by default to
+ * dispatch events to objects. Additionally, the main thread of the application
+ * (defined as the thread that calls CameraManager::start()) is also associated
+ * with a Thread instance, but has no event loop accessible to libcamera. Other
+ * application threads are not visible to libcamera.
+ *
+ * \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 internally by libcamera are bound to internal
+ * threads. As objects interact with thread event loops for proper operation,
+ * creating an Object instance in a thread that has no internal event loop (such
+ * as the main application thread, or libcamera threads that have a custom main
+ * loop), prevents some features of the Object class from being used. See
+ * Thread::exec() for more details.
+ *
+ * \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().
+ *
+ * \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.
+ *
+ * \section thread-stop Stopping Threads
+ *
+ * Threads can't be forcibly stopped. Instead, a thread user first requests the
+ * thread to exit and then waits for the thread's main function to react to the
+ * request and return, at which points the thread will stop.
+ *
+ * For threads running exec(), the exit() function is used to request the thread
+ * to exit. For threads subclassing the Thread class and implementing a custom
+ * run() function, a subclass-specific mechanism shall be provided. In either
+ * case, the wait() function shall be called to wait for the thread to stop.
+ *
+ * Due to their asynchronous nature, threads are subject to race conditions when
+ * they stop. This is of particular importance for messages posted to the thread
+ * with postMessage() (and the other mechanisms that rely on it, such as
+ * Object::invokeMethod() or asynchronous signal delivery). To understand the
+ * issues, three contexts need to be considered:
+ *
+ * - The worker is the Thread performing work and being instructed to stop.
+ * - The controller is the context which instructs the worker thread to stop.
+ * - The other contexts are any threads other than the worker and controller
+ *   that interact with the worker thread.
+ *
+ * Messages posted to the worker thread from the controller context before
+ * calling exit() are queued to the thread's message queue, and the Thread class
+ * offers no guarantee that those messages will be processed before the thread
+ * stops. This allows threads to stop fast.
+ *
+ * A thread that requires delivery of messages posted from the controller
+ * context before exit() should reimplement the run() function and call
+ * dispatchMessages() after exec().
+ *
+ * Messages posted to the worker thread from the other contexts are asynchronous
+ * with respect to the exit() call from the controller context. There is no
+ * guarantee as to whether those messages will be processed or not before the
+ * thread stops.
+ *
+ * Messages that are not processed will stay in the queue, in the exact same way
+ * as messages posted after the thread has stopped. They will be processed when
+ * the thread is restarted. If the thread is never restarted, they will be
+ * deleted without being processed when the Thread instance is destroyed.
+ */
diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
index b96951ac..6b034e06 100644
--- a/src/libcamera/base/thread.cpp
+++ b/src/libcamera/base/thread.cpp
@@ -19,88 +19,6 @@ 
 #include <libcamera/base/message.h>
 #include <libcamera/base/mutex.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.
- *
- * Every thread created by libcamera is associated with an instance of the
- * Thread class. Those threads run an internal event loop by default to
- * dispatch events to objects. Additionally, the main thread of the application
- * (defined as the thread that calls CameraManager::start()) is also associated
- * with a Thread instance, but has no event loop accessible to libcamera. Other
- * application threads are not visible to libcamera.
- *
- * \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 internally by libcamera are bound to internal
- * threads. As objects interact with thread event loops for proper operation,
- * creating an Object instance in a thread that has no internal event loop (such
- * as the main application thread, or libcamera threads that have a custom main
- * loop), prevents some features of the Object class from being used. See
- * Thread::exec() for more details.
- *
- * \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().
- *
- * \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 base/thread.h
  * \brief Thread support
@@ -216,47 +134,6 @@  ThreadData *ThreadData::current()
  * called. The event loop dispatches events (messages, notifiers and timers)
  * sent to the objects living in the thread. This behaviour can be modified by
  * overriding the run() function.
- *
- * \section thread-stop Stopping Threads
- *
- * Threads can't be forcibly stopped. Instead, a thread user first requests the
- * thread to exit and then waits for the thread's main function to react to the
- * request and return, at which points the thread will stop.
- *
- * For threads running exec(), the exit() function is used to request the thread
- * to exit. For threads subclassing the Thread class and implementing a custom
- * run() function, a subclass-specific mechanism shall be provided. In either
- * case, the wait() function shall be called to wait for the thread to stop.
- *
- * Due to their asynchronous nature, threads are subject to race conditions when
- * they stop. This is of particular importance for messages posted to the thread
- * with postMessage() (and the other mechanisms that rely on it, such as
- * Object::invokeMethod() or asynchronous signal delivery). To understand the
- * issues, three contexts need to be considered:
- *
- * - The worker is the Thread performing work and being instructed to stop.
- * - The controller is the context which instructs the worker thread to stop.
- * - The other contexts are any threads other than the worker and controller
- *   that interact with the worker thread.
- *
- * Messages posted to the worker thread from the controller context before
- * calling exit() are queued to the thread's message queue, and the Thread class
- * offers no guarantee that those messages will be processed before the thread
- * stops. This allows threads to stop fast.
- *
- * A thread that requires delivery of messages posted from the controller
- * context before exit() should reimplement the run() function and call
- * dispatchMessages() after exec().
- *
- * Messages posted to the worker thread from the other contexts are asynchronous
- * with respect to the exit() call from the controller context. There is no
- * guarantee as to whether those messages will be processed or not before the
- * thread stops.
- *
- * Messages that are not processed will stay in the queue, in the exact same way
- * as messages posted after the thread has stopped. They will be processed when
- * the thread is restarted. If the thread is never restarted, they will be
- * deleted without being processed when the Thread instance is destroyed.
  */
 
 /**