Show a patch.

GET /api/patches/19374/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 19374,
    "url": "https://patchwork.libcamera.org/api/patches/19374/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/19374/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20240105164104.78398-4-dan.scally@ideasonboard.com>",
    "date": "2024-01-05T16:41:02",
    "name": "[libcamera-devel,v2,3/5] Documentation: Add Thread support page",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "3cb6ae9cf858eb175587ba0715a1b032cdbbc236",
    "submitter": {
        "id": 156,
        "url": "https://patchwork.libcamera.org/api/people/156/?format=api",
        "name": "Dan Scally",
        "email": "dan.scally@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/19374/mbox/",
    "series": [
        {
            "id": 4134,
            "url": "https://patchwork.libcamera.org/api/series/4134/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4134",
            "date": "2024-01-05T16:40:59",
            "name": "Improve libcamera documentation",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/4134/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/19374/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/19374/checks/",
    "tags": {},
    "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 EAC1AC32BC\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  5 Jan 2024 16:41:28 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7DA2E62B53;\n\tFri,  5 Jan 2024 17:41:28 +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 B754662B49\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  5 Jan 2024 17:41:22 +0100 (CET)",
            "from mail.ideasonboard.com\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 50A8FD49;\n\tFri,  5 Jan 2024 17:40:21 +0100 (CET)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704472888;\n\tbh=oF2MZX1y0uQraRg0qMd6I/qnzRrOIfwYV/WDvHqU/aA=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=vevVRGA4ic+CjOCPcpoOwYm66/IEvFem6PhG5jeEK1XE4SAO6DqJec9Z/Oi3rT2Sm\n\tC48HInWZj0QgmcReMSSttLbC7t8PWVWOMiMGEI1fs8d18mmAEXh6qTkWP5pugL9yOg\n\tyVY+2Pd8krNDxJ2AEBcY+CIqwZpF4somCVvkI2uw+AGKLuU7HD+iQ5lmAWvB5aIU92\n\t/VM/P7ItxdINahLlsggIHCMmfK8eJWYMzCZjX/kaRhTo2SstfuPyV7hxtDFjWqUOLl\n\tX+1OhaRsVWsb+sBkc7NPHCxeOHdtTJqHEUi15ijcx5x+XeFn7qfdPE/8kL8YUPzmvZ\n\tKppx9k4zSoTpA==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704472821;\n\tbh=oF2MZX1y0uQraRg0qMd6I/qnzRrOIfwYV/WDvHqU/aA=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=aJE7AVt25UZcSv9oD3ahFUVZDP621em9Gg91ojpgSvulXU0dV/hr/6+eqLeaPOaCx\n\tmvXkEw0jh6xhkryggVFqx1syu9BVemlHJITRDzbLD6dtRQEJHUsLMN/Y0CMKT9L+sV\n\tU49agvfBdCHXlJRChF0RTkAn2ZbjADgiNBuhSVoI="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"aJE7AVt2\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Fri,  5 Jan 2024 16:41:02 +0000",
        "Message-Id": "<20240105164104.78398-4-dan.scally@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20240105164104.78398-1-dan.scally@ideasonboard.com>",
        "References": "<20240105164104.78398-1-dan.scally@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v2 3/5] Documentation: Add Thread support\n\tpage",
        "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": "Daniel Scally via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Daniel Scally <dan.scally@ideasonboard.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Move the Thread Support page and the section of the Thread class'\ndocumentation dealing with stopping threads from\nsrc/libcamera/base/thread.cpp to a dedicated .dox file at\nDocumentation/. This is done to support the splitting of the\nDocumentation into a public and internal version. With a separate\npage, references can be made to thread safety without having to\ninclude the Thread class in the doxygen run.\n\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n---\nChanges 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",
    "diff": "diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\nindex 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 \ndiff --git a/Documentation/thread.dox b/Documentation/thread.dox\nnew file mode 100644\nindex 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+ */\ndiff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp\nindex 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",
    "prefixes": [
        "libcamera-devel",
        "v2",
        "3/5"
    ]
}