[{"id":28423,"web_url":"https://patchwork.libcamera.org/comment/28423/","msgid":"<sapn4xp5sfli72ruap4kf4lod4yq6eaav2bfg25p47mynjqk7r@iillmqaxg23h>","date":"2024-01-09T14:06:19","subject":"Re: [libcamera-devel] [PATCH v2 3/5] Documentation: Add Thread\n\tsupport page","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Dan\n\nOn Fri, Jan 05, 2024 at 04:41:02PM +0000, Daniel Scally via libcamera-devel wrote:\n> Move the Thread Support page and the section of the Thread class'\n> documentation dealing with stopping threads from\n> src/libcamera/base/thread.cpp to a dedicated .dox file at\n> Documentation/. This is done to support the splitting of the\n> Documentation into a public and internal version. With a separate\n> page, references can be made to thread safety without having to\n> include the Thread class in the doxygen run.\n>\n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n\nLooks good!\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\n> ---\n> Changes in v2:\n>\n> \t- New patch\n>\n>  Documentation/Doxyfile.in     |   6 +-\n>  Documentation/thread.dox      | 122 +++++++++++++++++++++++++++++++++\n>  src/libcamera/base/thread.cpp | 123 ----------------------------------\n>  3 files changed, 126 insertions(+), 125 deletions(-)\n>  create mode 100644 Documentation/thread.dox\n>\n> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> index a86ea6c1..48fea8bc 100644\n> --- a/Documentation/Doxyfile.in\n> +++ b/Documentation/Doxyfile.in\n> @@ -21,7 +21,8 @@ CASE_SENSE_NAMES       = YES\n>\n>  QUIET                  = YES\n>\n> -INPUT                  = \"@TOP_SRCDIR@/include/libcamera\" \\\n> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>                           \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>                           \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>                           \"@TOP_SRCDIR@/src/libcamera\" \\\n> @@ -30,7 +31,8 @@ INPUT                  = \"@TOP_SRCDIR@/include/libcamera\" \\\n>\n>  FILE_PATTERNS          = *.c \\\n>                           *.cpp \\\n> -                         *.h\n> +                         *.h \\\n> +\t\t\t *.dox\n>\n>  RECURSIVE              = YES\n>\n> diff --git a/Documentation/thread.dox b/Documentation/thread.dox\n> new file mode 100644\n> index 00000000..805a864e\n> --- /dev/null\n> +++ b/Documentation/thread.dox\n> @@ -0,0 +1,122 @@\n> +/**\n> + * \\page thread Thread Support\n> + *\n> + * libcamera supports multi-threaded applications through a threading model that\n> + * sets precise rules to guarantee thread-safe usage of the API. Additionally,\n> + * libcamera makes internal use of threads, and offers APIs that simplify\n> + * interactions with application threads. Careful compliance with the threading\n> + * model will ensure avoidance of race conditions.\n> + *\n> + * Every thread created by libcamera is associated with an instance of the\n> + * Thread class. Those threads run an internal event loop by default to\n> + * dispatch events to objects. Additionally, the main thread of the application\n> + * (defined as the thread that calls CameraManager::start()) is also associated\n> + * with a Thread instance, but has no event loop accessible to libcamera. Other\n> + * application threads are not visible to libcamera.\n> + *\n> + * \\section thread-objects Threads and Objects\n> + *\n> + * Instances of the Object class and all its derived classes are thread-aware\n> + * and are bound to the thread they are created in. They are said to *live* in\n> + * a thread, and they interact with the event loop of their thread for the\n> + * purpose of message passing and signal delivery. Messages posted to the\n> + * object with Object::postMessage() will be delivered from the event loop of\n> + * the thread that the object lives in. Signals delivered to the object, unless\n> + * explicitly connected with ConnectionTypeDirect, will also be delivered from\n> + * the object thread's event loop.\n> + *\n> + * All Object instances created internally by libcamera are bound to internal\n> + * threads. As objects interact with thread event loops for proper operation,\n> + * creating an Object instance in a thread that has no internal event loop (such\n> + * as the main application thread, or libcamera threads that have a custom main\n> + * loop), prevents some features of the Object class from being used. See\n> + * Thread::exec() for more details.\n> + *\n> + * \\section thread-signals Threads and Signals\n> + *\n> + * When sent to a receiver that does not inherit from the Object class, signals\n> + * are delivered synchronously in the thread of the sender. When the receiver\n> + * inherits from the Object class, delivery is by default asynchronous if the\n> + * sender and receiver live in different threads. In that case, the signal is\n> + * posted to the receiver's message queue and will be delivered from the\n> + * receiver's event loop, running in the receiver's thread. This mechanism can\n> + * be overridden by selecting a different connection type when calling\n> + * Signal::connect().\n> + *\n> + * \\section thread-reentrancy Reentrancy and Thread-Safety\n> + *\n> + * Through the documentation, several terms are used to define how classes and\n> + * their member functions can be used from multiple threads.\n> + *\n> + * - A **reentrant** function may be called simultaneously from multiple\n> + *   threads if and only if each invocation uses a different instance of the\n> + *   class. This is the default for all member functions not explictly marked\n> + *   otherwise.\n> + *\n> + * - \\anchor thread-safe A **thread-safe** function may be called\n> + *   simultaneously from multiple threads on the same instance of a class. A\n> + *   thread-safe function is thus reentrant. Thread-safe functions may also be\n> + *   called simultaneously with any other reentrant function of the same class\n> + *   on the same instance.\n> + *\n> + * - \\anchor thread-bound A **thread-bound** function may be called only from\n> + *   the thread that the class instances lives in (see section \\ref\n> + *   thread-objects). For instances of classes that do not derive from the\n> + *   Object class, this is the thread in which the instance was created. A\n> + *   thread-bound function is not thread-safe, and may or may not be reentrant.\n> + *\n> + * Neither reentrancy nor thread-safety, in this context, mean that a function\n> + * may be called simultaneously from the same thread, for instance from a\n> + * callback invoked by the function. This may deadlock and isn't allowed unless\n> + * separately documented.\n> + *\n> + * A class is defined as reentrant, thread-safe or thread-bound if all its\n> + * member functions are reentrant, thread-safe or thread-bound respectively.\n> + * Some member functions may additionally be documented as having additional\n> + * thread-related attributes.\n> + *\n> + * Most classes are reentrant but not thread-safe, as making them fully\n> + * thread-safe would incur locking costs considered prohibitive for the\n> + * expected use cases.\n> + *\n> + * \\section thread-stop Stopping Threads\n> + *\n> + * Threads can't be forcibly stopped. Instead, a thread user first requests the\n> + * thread to exit and then waits for the thread's main function to react to the\n> + * request and return, at which points the thread will stop.\n> + *\n> + * For threads running exec(), the exit() function is used to request the thread\n> + * to exit. For threads subclassing the Thread class and implementing a custom\n> + * run() function, a subclass-specific mechanism shall be provided. In either\n> + * case, the wait() function shall be called to wait for the thread to stop.\n> + *\n> + * Due to their asynchronous nature, threads are subject to race conditions when\n> + * they stop. This is of particular importance for messages posted to the thread\n> + * with postMessage() (and the other mechanisms that rely on it, such as\n> + * Object::invokeMethod() or asynchronous signal delivery). To understand the\n> + * issues, three contexts need to be considered:\n> + *\n> + * - The worker is the Thread performing work and being instructed to stop.\n> + * - The controller is the context which instructs the worker thread to stop.\n> + * - The other contexts are any threads other than the worker and controller\n> + *   that interact with the worker thread.\n> + *\n> + * Messages posted to the worker thread from the controller context before\n> + * calling exit() are queued to the thread's message queue, and the Thread class\n> + * offers no guarantee that those messages will be processed before the thread\n> + * stops. This allows threads to stop fast.\n> + *\n> + * A thread that requires delivery of messages posted from the controller\n> + * context before exit() should reimplement the run() function and call\n> + * dispatchMessages() after exec().\n> + *\n> + * Messages posted to the worker thread from the other contexts are asynchronous\n> + * with respect to the exit() call from the controller context. There is no\n> + * guarantee as to whether those messages will be processed or not before the\n> + * thread stops.\n> + *\n> + * Messages that are not processed will stay in the queue, in the exact same way\n> + * as messages posted after the thread has stopped. They will be processed when\n> + * the thread is restarted. If the thread is never restarted, they will be\n> + * deleted without being processed when the Thread instance is destroyed.\n> + */\n> diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp\n> index b96951ac..6b034e06 100644\n> --- a/src/libcamera/base/thread.cpp\n> +++ b/src/libcamera/base/thread.cpp\n> @@ -19,88 +19,6 @@\n>  #include <libcamera/base/message.h>\n>  #include <libcamera/base/mutex.h>\n>\n> -/**\n> - * \\page thread Thread Support\n> - *\n> - * libcamera supports multi-threaded applications through a threading model that\n> - * sets precise rules to guarantee thread-safe usage of the API. Additionally,\n> - * libcamera makes internal use of threads, and offers APIs that simplify\n> - * interactions with application threads. Careful compliance with the threading\n> - * model will ensure avoidance of race conditions.\n> - *\n> - * Every thread created by libcamera is associated with an instance of the\n> - * Thread class. Those threads run an internal event loop by default to\n> - * dispatch events to objects. Additionally, the main thread of the application\n> - * (defined as the thread that calls CameraManager::start()) is also associated\n> - * with a Thread instance, but has no event loop accessible to libcamera. Other\n> - * application threads are not visible to libcamera.\n> - *\n> - * \\section thread-objects Threads and Objects\n> - *\n> - * Instances of the Object class and all its derived classes are thread-aware\n> - * and are bound to the thread they are created in. They are said to *live* in\n> - * a thread, and they interact with the event loop of their thread for the\n> - * purpose of message passing and signal delivery. Messages posted to the\n> - * object with Object::postMessage() will be delivered from the event loop of\n> - * the thread that the object lives in. Signals delivered to the object, unless\n> - * explicitly connected with ConnectionTypeDirect, will also be delivered from\n> - * the object thread's event loop.\n> - *\n> - * All Object instances created internally by libcamera are bound to internal\n> - * threads. As objects interact with thread event loops for proper operation,\n> - * creating an Object instance in a thread that has no internal event loop (such\n> - * as the main application thread, or libcamera threads that have a custom main\n> - * loop), prevents some features of the Object class from being used. See\n> - * Thread::exec() for more details.\n> - *\n> - * \\section thread-signals Threads and Signals\n> - *\n> - * When sent to a receiver that does not inherit from the Object class, signals\n> - * are delivered synchronously in the thread of the sender. When the receiver\n> - * inherits from the Object class, delivery is by default asynchronous if the\n> - * sender and receiver live in different threads. In that case, the signal is\n> - * posted to the receiver's message queue and will be delivered from the\n> - * receiver's event loop, running in the receiver's thread. This mechanism can\n> - * be overridden by selecting a different connection type when calling\n> - * Signal::connect().\n> - *\n> - * \\section thread-reentrancy Reentrancy and Thread-Safety\n> - *\n> - * Through the documentation, several terms are used to define how classes and\n> - * their member functions can be used from multiple threads.\n> - *\n> - * - A **reentrant** function may be called simultaneously from multiple\n> - *   threads if and only if each invocation uses a different instance of the\n> - *   class. This is the default for all member functions not explictly marked\n> - *   otherwise.\n> - *\n> - * - \\anchor thread-safe A **thread-safe** function may be called\n> - *   simultaneously from multiple threads on the same instance of a class. A\n> - *   thread-safe function is thus reentrant. Thread-safe functions may also be\n> - *   called simultaneously with any other reentrant function of the same class\n> - *   on the same instance.\n> - *\n> - * - \\anchor thread-bound A **thread-bound** function may be called only from\n> - *   the thread that the class instances lives in (see section \\ref\n> - *   thread-objects). For instances of classes that do not derive from the\n> - *   Object class, this is the thread in which the instance was created. A\n> - *   thread-bound function is not thread-safe, and may or may not be reentrant.\n> - *\n> - * Neither reentrancy nor thread-safety, in this context, mean that a function\n> - * may be called simultaneously from the same thread, for instance from a\n> - * callback invoked by the function. This may deadlock and isn't allowed unless\n> - * separately documented.\n> - *\n> - * A class is defined as reentrant, thread-safe or thread-bound if all its\n> - * member functions are reentrant, thread-safe or thread-bound respectively.\n> - * Some member functions may additionally be documented as having additional\n> - * thread-related attributes.\n> - *\n> - * Most classes are reentrant but not thread-safe, as making them fully\n> - * thread-safe would incur locking costs considered prohibitive for the\n> - * expected use cases.\n> - */\n> -\n>  /**\n>   * \\file base/thread.h\n>   * \\brief Thread support\n> @@ -216,47 +134,6 @@ ThreadData *ThreadData::current()\n>   * called. The event loop dispatches events (messages, notifiers and timers)\n>   * sent to the objects living in the thread. This behaviour can be modified by\n>   * overriding the run() function.\n> - *\n> - * \\section thread-stop Stopping Threads\n> - *\n> - * Threads can't be forcibly stopped. Instead, a thread user first requests the\n> - * thread to exit and then waits for the thread's main function to react to the\n> - * request and return, at which points the thread will stop.\n> - *\n> - * For threads running exec(), the exit() function is used to request the thread\n> - * to exit. For threads subclassing the Thread class and implementing a custom\n> - * run() function, a subclass-specific mechanism shall be provided. In either\n> - * case, the wait() function shall be called to wait for the thread to stop.\n> - *\n> - * Due to their asynchronous nature, threads are subject to race conditions when\n> - * they stop. This is of particular importance for messages posted to the thread\n> - * with postMessage() (and the other mechanisms that rely on it, such as\n> - * Object::invokeMethod() or asynchronous signal delivery). To understand the\n> - * issues, three contexts need to be considered:\n> - *\n> - * - The worker is the Thread performing work and being instructed to stop.\n> - * - The controller is the context which instructs the worker thread to stop.\n> - * - The other contexts are any threads other than the worker and controller\n> - *   that interact with the worker thread.\n> - *\n> - * Messages posted to the worker thread from the controller context before\n> - * calling exit() are queued to the thread's message queue, and the Thread class\n> - * offers no guarantee that those messages will be processed before the thread\n> - * stops. This allows threads to stop fast.\n> - *\n> - * A thread that requires delivery of messages posted from the controller\n> - * context before exit() should reimplement the run() function and call\n> - * dispatchMessages() after exec().\n> - *\n> - * Messages posted to the worker thread from the other contexts are asynchronous\n> - * with respect to the exit() call from the controller context. There is no\n> - * guarantee as to whether those messages will be processed or not before the\n> - * thread stops.\n> - *\n> - * Messages that are not processed will stay in the queue, in the exact same way\n> - * as messages posted after the thread has stopped. They will be processed when\n> - * the thread is restarted. If the thread is never restarted, they will be\n> - * deleted without being processed when the Thread instance is destroyed.\n>   */\n>\n>  /**\n> --\n> 2.34.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 021E5C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  9 Jan 2024 14:06:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3FCD862B41;\n\tTue,  9 Jan 2024 15:06:24 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A576761D7B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jan 2024 15:06:22 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2001:b07:5d2e:52c9:cc1e:e404:491f:e6ea])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 97F18552;\n\tTue,  9 Jan 2024 15:05:18 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704809184;\n\tbh=azOj/ed9rMranlJDRQ4m3qU0l9ZkIamjLuLEH3lFMeY=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=i6GCbQj4bWMCM+q1nCgQMQb/KjnhyXnnoOHW2wVbRpP1fN2yyBjLhVgpot5djBdMr\n\t6iWX/JiTnkiglaYfhtNzFqlTMAQ/NHUFhmKwXaFEXei/PWDVdHH4uB1+eM+dWc3q/D\n\tTsrQS66+gHq5DoBTajVYYtJFY0YAVMqVyKxp/zZrYrO7J98aX3kZNhIz57lzuqbqG/\n\t1M0Piv2YUPoY3t16usRsB6r/hzd60LaJ0vlZRiPzgY5H9XC1mVq1+goLj6qsUAa31e\n\tmqX2dksUIXRoCE7yh9hkJADLBE17t9p0QJYIc455zvH5M+QsU9soARgYFRkQ8IUYt9\n\t6rQiuyW7Ejewg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704809118;\n\tbh=azOj/ed9rMranlJDRQ4m3qU0l9ZkIamjLuLEH3lFMeY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Qvjm7y6B4rSk2MIu3n8mqBIr5aCViCoqbRlWWwyEvgikShvR1Jp9jl4HI49WquP0K\n\t5zKqKlVdLsIB4UDIQZyrzex6imx11UfS85o/mMcHhURlA3IsgqAvrpn+5nfu3hv7To\n\t+Zf1jbKt2Qz7WY0rA3z3xwd/8fo7rmH6uyKcmI/I="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"Qvjm7y6B\"; dkim-atps=neutral","Date":"Tue, 9 Jan 2024 15:06:19 +0100","To":"Daniel Scally <dan.scally@ideasonboard.com>","Message-ID":"<sapn4xp5sfli72ruap4kf4lod4yq6eaav2bfg25p47mynjqk7r@iillmqaxg23h>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-4-dan.scally@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240105164104.78398-4-dan.scally@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 3/5] Documentation: Add Thread\n\tsupport page","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28438,"web_url":"https://patchwork.libcamera.org/comment/28438/","msgid":"<170482378089.3044059.10901838553014120230@ping.linuxembedded.co.uk>","date":"2024-01-09T18:09:40","subject":"Re: [libcamera-devel] [PATCH v2 3/5] Documentation: Add Thread\n\tsupport page","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Daniel Scally via libcamera-devel (2024-01-05 16:41:02)\n> Move the Thread Support page and the section of the Thread class'\n> documentation dealing with stopping threads from\n> src/libcamera/base/thread.cpp to a dedicated .dox file at\n> Documentation/. This is done to support the splitting of the\n> Documentation into a public and internal version. With a separate\n> page, references can be made to thread safety without having to\n> include the Thread class in the doxygen run.\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> \n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> ---\n> Changes in v2:\n> \n>         - New patch\n> \n>  Documentation/Doxyfile.in     |   6 +-\n>  Documentation/thread.dox      | 122 +++++++++++++++++++++++++++++++++\n>  src/libcamera/base/thread.cpp | 123 ----------------------------------\n>  3 files changed, 126 insertions(+), 125 deletions(-)\n>  create mode 100644 Documentation/thread.dox\n> \n> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> index a86ea6c1..48fea8bc 100644\n> --- a/Documentation/Doxyfile.in\n> +++ b/Documentation/Doxyfile.in\n> @@ -21,7 +21,8 @@ CASE_SENSE_NAMES       = YES\n>  \n>  QUIET                  = YES\n>  \n> -INPUT                  = \"@TOP_SRCDIR@/include/libcamera\" \\\n> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>                           \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>                           \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>                           \"@TOP_SRCDIR@/src/libcamera\" \\\n> @@ -30,7 +31,8 @@ INPUT                  = \"@TOP_SRCDIR@/include/libcamera\" \\\n>  \n>  FILE_PATTERNS          = *.c \\\n>                           *.cpp \\\n> -                         *.h\n> +                         *.h \\\n> +                        *.dox\n>  \n>  RECURSIVE              = YES\n>  \n> diff --git a/Documentation/thread.dox b/Documentation/thread.dox\n> new file mode 100644\n> index 00000000..805a864e\n> --- /dev/null\n> +++ b/Documentation/thread.dox\n> @@ -0,0 +1,122 @@\n> +/**\n> + * \\page thread Thread Support\n> + *\n> + * libcamera supports multi-threaded applications through a threading model that\n> + * sets precise rules to guarantee thread-safe usage of the API. Additionally,\n> + * libcamera makes internal use of threads, and offers APIs that simplify\n> + * interactions with application threads. Careful compliance with the threading\n> + * model will ensure avoidance of race conditions.\n> + *\n> + * Every thread created by libcamera is associated with an instance of the\n> + * Thread class. Those threads run an internal event loop by default to\n> + * dispatch events to objects. Additionally, the main thread of the application\n> + * (defined as the thread that calls CameraManager::start()) is also associated\n> + * with a Thread instance, but has no event loop accessible to libcamera. Other\n> + * application threads are not visible to libcamera.\n> + *\n> + * \\section thread-objects Threads and Objects\n> + *\n> + * Instances of the Object class and all its derived classes are thread-aware\n> + * and are bound to the thread they are created in. They are said to *live* in\n> + * a thread, and they interact with the event loop of their thread for the\n> + * purpose of message passing and signal delivery. Messages posted to the\n> + * object with Object::postMessage() will be delivered from the event loop of\n> + * the thread that the object lives in. Signals delivered to the object, unless\n> + * explicitly connected with ConnectionTypeDirect, will also be delivered from\n> + * the object thread's event loop.\n> + *\n> + * All Object instances created internally by libcamera are bound to internal\n> + * threads. As objects interact with thread event loops for proper operation,\n> + * creating an Object instance in a thread that has no internal event loop (such\n> + * as the main application thread, or libcamera threads that have a custom main\n> + * loop), prevents some features of the Object class from being used. See\n> + * Thread::exec() for more details.\n> + *\n> + * \\section thread-signals Threads and Signals\n> + *\n> + * When sent to a receiver that does not inherit from the Object class, signals\n> + * are delivered synchronously in the thread of the sender. When the receiver\n> + * inherits from the Object class, delivery is by default asynchronous if the\n> + * sender and receiver live in different threads. In that case, the signal is\n> + * posted to the receiver's message queue and will be delivered from the\n> + * receiver's event loop, running in the receiver's thread. This mechanism can\n> + * be overridden by selecting a different connection type when calling\n> + * Signal::connect().\n> + *\n> + * \\section thread-reentrancy Reentrancy and Thread-Safety\n> + *\n> + * Through the documentation, several terms are used to define how classes and\n> + * their member functions can be used from multiple threads.\n> + *\n> + * - A **reentrant** function may be called simultaneously from multiple\n> + *   threads if and only if each invocation uses a different instance of the\n> + *   class. This is the default for all member functions not explictly marked\n> + *   otherwise.\n> + *\n> + * - \\anchor thread-safe A **thread-safe** function may be called\n> + *   simultaneously from multiple threads on the same instance of a class. A\n> + *   thread-safe function is thus reentrant. Thread-safe functions may also be\n> + *   called simultaneously with any other reentrant function of the same class\n> + *   on the same instance.\n> + *\n> + * - \\anchor thread-bound A **thread-bound** function may be called only from\n> + *   the thread that the class instances lives in (see section \\ref\n> + *   thread-objects). For instances of classes that do not derive from the\n> + *   Object class, this is the thread in which the instance was created. A\n> + *   thread-bound function is not thread-safe, and may or may not be reentrant.\n> + *\n> + * Neither reentrancy nor thread-safety, in this context, mean that a function\n> + * may be called simultaneously from the same thread, for instance from a\n> + * callback invoked by the function. This may deadlock and isn't allowed unless\n> + * separately documented.\n> + *\n> + * A class is defined as reentrant, thread-safe or thread-bound if all its\n> + * member functions are reentrant, thread-safe or thread-bound respectively.\n> + * Some member functions may additionally be documented as having additional\n> + * thread-related attributes.\n> + *\n> + * Most classes are reentrant but not thread-safe, as making them fully\n> + * thread-safe would incur locking costs considered prohibitive for the\n> + * expected use cases.\n> + *\n> + * \\section thread-stop Stopping Threads\n> + *\n> + * Threads can't be forcibly stopped. Instead, a thread user first requests the\n> + * thread to exit and then waits for the thread's main function to react to the\n> + * request and return, at which points the thread will stop.\n> + *\n> + * For threads running exec(), the exit() function is used to request the thread\n> + * to exit. For threads subclassing the Thread class and implementing a custom\n> + * run() function, a subclass-specific mechanism shall be provided. In either\n> + * case, the wait() function shall be called to wait for the thread to stop.\n> + *\n> + * Due to their asynchronous nature, threads are subject to race conditions when\n> + * they stop. This is of particular importance for messages posted to the thread\n> + * with postMessage() (and the other mechanisms that rely on it, such as\n> + * Object::invokeMethod() or asynchronous signal delivery). To understand the\n> + * issues, three contexts need to be considered:\n> + *\n> + * - The worker is the Thread performing work and being instructed to stop.\n> + * - The controller is the context which instructs the worker thread to stop.\n> + * - The other contexts are any threads other than the worker and controller\n> + *   that interact with the worker thread.\n> + *\n> + * Messages posted to the worker thread from the controller context before\n> + * calling exit() are queued to the thread's message queue, and the Thread class\n> + * offers no guarantee that those messages will be processed before the thread\n> + * stops. This allows threads to stop fast.\n> + *\n> + * A thread that requires delivery of messages posted from the controller\n> + * context before exit() should reimplement the run() function and call\n> + * dispatchMessages() after exec().\n> + *\n> + * Messages posted to the worker thread from the other contexts are asynchronous\n> + * with respect to the exit() call from the controller context. There is no\n> + * guarantee as to whether those messages will be processed or not before the\n> + * thread stops.\n> + *\n> + * Messages that are not processed will stay in the queue, in the exact same way\n> + * as messages posted after the thread has stopped. They will be processed when\n> + * the thread is restarted. If the thread is never restarted, they will be\n> + * deleted without being processed when the Thread instance is destroyed.\n> + */\n> diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp\n> index b96951ac..6b034e06 100644\n> --- a/src/libcamera/base/thread.cpp\n> +++ b/src/libcamera/base/thread.cpp\n> @@ -19,88 +19,6 @@\n>  #include <libcamera/base/message.h>\n>  #include <libcamera/base/mutex.h>\n>  \n> -/**\n> - * \\page thread Thread Support\n> - *\n> - * libcamera supports multi-threaded applications through a threading model that\n> - * sets precise rules to guarantee thread-safe usage of the API. Additionally,\n> - * libcamera makes internal use of threads, and offers APIs that simplify\n> - * interactions with application threads. Careful compliance with the threading\n> - * model will ensure avoidance of race conditions.\n> - *\n> - * Every thread created by libcamera is associated with an instance of the\n> - * Thread class. Those threads run an internal event loop by default to\n> - * dispatch events to objects. Additionally, the main thread of the application\n> - * (defined as the thread that calls CameraManager::start()) is also associated\n> - * with a Thread instance, but has no event loop accessible to libcamera. Other\n> - * application threads are not visible to libcamera.\n> - *\n> - * \\section thread-objects Threads and Objects\n> - *\n> - * Instances of the Object class and all its derived classes are thread-aware\n> - * and are bound to the thread they are created in. They are said to *live* in\n> - * a thread, and they interact with the event loop of their thread for the\n> - * purpose of message passing and signal delivery. Messages posted to the\n> - * object with Object::postMessage() will be delivered from the event loop of\n> - * the thread that the object lives in. Signals delivered to the object, unless\n> - * explicitly connected with ConnectionTypeDirect, will also be delivered from\n> - * the object thread's event loop.\n> - *\n> - * All Object instances created internally by libcamera are bound to internal\n> - * threads. As objects interact with thread event loops for proper operation,\n> - * creating an Object instance in a thread that has no internal event loop (such\n> - * as the main application thread, or libcamera threads that have a custom main\n> - * loop), prevents some features of the Object class from being used. See\n> - * Thread::exec() for more details.\n> - *\n> - * \\section thread-signals Threads and Signals\n> - *\n> - * When sent to a receiver that does not inherit from the Object class, signals\n> - * are delivered synchronously in the thread of the sender. When the receiver\n> - * inherits from the Object class, delivery is by default asynchronous if the\n> - * sender and receiver live in different threads. In that case, the signal is\n> - * posted to the receiver's message queue and will be delivered from the\n> - * receiver's event loop, running in the receiver's thread. This mechanism can\n> - * be overridden by selecting a different connection type when calling\n> - * Signal::connect().\n> - *\n> - * \\section thread-reentrancy Reentrancy and Thread-Safety\n> - *\n> - * Through the documentation, several terms are used to define how classes and\n> - * their member functions can be used from multiple threads.\n> - *\n> - * - A **reentrant** function may be called simultaneously from multiple\n> - *   threads if and only if each invocation uses a different instance of the\n> - *   class. This is the default for all member functions not explictly marked\n> - *   otherwise.\n> - *\n> - * - \\anchor thread-safe A **thread-safe** function may be called\n> - *   simultaneously from multiple threads on the same instance of a class. A\n> - *   thread-safe function is thus reentrant. Thread-safe functions may also be\n> - *   called simultaneously with any other reentrant function of the same class\n> - *   on the same instance.\n> - *\n> - * - \\anchor thread-bound A **thread-bound** function may be called only from\n> - *   the thread that the class instances lives in (see section \\ref\n> - *   thread-objects). For instances of classes that do not derive from the\n> - *   Object class, this is the thread in which the instance was created. A\n> - *   thread-bound function is not thread-safe, and may or may not be reentrant.\n> - *\n> - * Neither reentrancy nor thread-safety, in this context, mean that a function\n> - * may be called simultaneously from the same thread, for instance from a\n> - * callback invoked by the function. This may deadlock and isn't allowed unless\n> - * separately documented.\n> - *\n> - * A class is defined as reentrant, thread-safe or thread-bound if all its\n> - * member functions are reentrant, thread-safe or thread-bound respectively.\n> - * Some member functions may additionally be documented as having additional\n> - * thread-related attributes.\n> - *\n> - * Most classes are reentrant but not thread-safe, as making them fully\n> - * thread-safe would incur locking costs considered prohibitive for the\n> - * expected use cases.\n> - */\n> -\n>  /**\n>   * \\file base/thread.h\n>   * \\brief Thread support\n> @@ -216,47 +134,6 @@ ThreadData *ThreadData::current()\n>   * called. The event loop dispatches events (messages, notifiers and timers)\n>   * sent to the objects living in the thread. This behaviour can be modified by\n>   * overriding the run() function.\n> - *\n> - * \\section thread-stop Stopping Threads\n> - *\n> - * Threads can't be forcibly stopped. Instead, a thread user first requests the\n> - * thread to exit and then waits for the thread's main function to react to the\n> - * request and return, at which points the thread will stop.\n> - *\n> - * For threads running exec(), the exit() function is used to request the thread\n> - * to exit. For threads subclassing the Thread class and implementing a custom\n> - * run() function, a subclass-specific mechanism shall be provided. In either\n> - * case, the wait() function shall be called to wait for the thread to stop.\n> - *\n> - * Due to their asynchronous nature, threads are subject to race conditions when\n> - * they stop. This is of particular importance for messages posted to the thread\n> - * with postMessage() (and the other mechanisms that rely on it, such as\n> - * Object::invokeMethod() or asynchronous signal delivery). To understand the\n> - * issues, three contexts need to be considered:\n> - *\n> - * - The worker is the Thread performing work and being instructed to stop.\n> - * - The controller is the context which instructs the worker thread to stop.\n> - * - The other contexts are any threads other than the worker and controller\n> - *   that interact with the worker thread.\n> - *\n> - * Messages posted to the worker thread from the controller context before\n> - * calling exit() are queued to the thread's message queue, and the Thread class\n> - * offers no guarantee that those messages will be processed before the thread\n> - * stops. This allows threads to stop fast.\n> - *\n> - * A thread that requires delivery of messages posted from the controller\n> - * context before exit() should reimplement the run() function and call\n> - * dispatchMessages() after exec().\n> - *\n> - * Messages posted to the worker thread from the other contexts are asynchronous\n> - * with respect to the exit() call from the controller context. There is no\n> - * guarantee as to whether those messages will be processed or not before the\n> - * thread stops.\n> - *\n> - * Messages that are not processed will stay in the queue, in the exact same way\n> - * as messages posted after the thread has stopped. They will be processed when\n> - * the thread is restarted. If the thread is never restarted, they will be\n> - * deleted without being processed when the Thread instance is destroyed.\n>   */\n>  \n>  /**\n> -- \n> 2.34.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E7758BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  9 Jan 2024 18:09:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D36F962B5E;\n\tTue,  9 Jan 2024 19:09:45 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2CAE261D76\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jan 2024 19:09:44 +0100 (CET)","from pendragon.ideasonboard.com\n\t(aztw-30-b2-v4wan-166917-cust845.vm26.cable.virginm.net\n\t[82.37.23.78])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D236A922;\n\tTue,  9 Jan 2024 19:08:39 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704823785;\n\tbh=cF5py7L7YBBtBfQLTvGgj8RCJR9bHSp9vqPV/81f820=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=NXorCMBwOmy91nCi1NiILymM758nt40iz+E2CAVwjx1TPfLL964tahaBzblN8Ljmv\n\txnvhujGlmh2v1W9GoGGU3XmtzJeP5De39OcaqzsswZ3Cfuze3C5MUpyAeB5xfEUvFo\n\t97fWlzcRf9D8kYaik9RJMUGV6Azm/6quslVE/moWPBMxHjXsQ98tPYM0NGDw0rspXq\n\thKbvi0/rZ28BXKZWoGMd8FuyNNV++H0rkfFjifGQsmELpowOYnZRao60xGlp9VXQtR\n\tZCEw2kVl+VKzu4LUiRKIhiWIrfV7QXDIiQShmq5M08jlLiMEzZYEAEaP8cIoWp/HFb\n\tR6JdFT7SpLTuA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704823719;\n\tbh=cF5py7L7YBBtBfQLTvGgj8RCJR9bHSp9vqPV/81f820=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=kSyy3k7y7hUuaO56gp1Jpq4meTo/JDX3JdPdnYWJkWd7d7zynYivLHJl5cC07UKIF\n\tLAgoxmkFJ5GmToKlCIysGx2BGi7pZq4FZZq4pqrHnn97lT686UmApqc779UiomzQnP\n\t+pYuv7KgX/DjrvHgL1+6bDS+mbnICBWubh00U5bA="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"kSyy3k7y\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240105164104.78398-4-dan.scally@ideasonboard.com>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-4-dan.scally@ideasonboard.com>","To":"Daniel Scally <dan.scally@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 09 Jan 2024 18:09:40 +0000","Message-ID":"<170482378089.3044059.10901838553014120230@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v2 3/5] Documentation: Add Thread\n\tsupport page","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]