Message ID | 20200120002437.6633-11-laurent.pinchart@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On Mon, Jan 20, 2020 at 02:24:28AM +0200, Laurent Pinchart wrote: > Document the design of libcamera's threading support, and prepare to > document thread-safety of classes and functions with a doxygen alias > command. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Documentation/Doxyfile.in | 4 +- > src/libcamera/thread.cpp | 82 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in > index 8e6fbdbb92b6..734672ed15dc 100644 > --- a/Documentation/Doxyfile.in > +++ b/Documentation/Doxyfile.in > @@ -239,7 +239,9 @@ TAB_SIZE = 4 > # newlines (in the resulting output). You can put ^^ in the value part of an > # alias to insert a newline as if a physical newline was in the original file. > > -ALIASES = > +ALIASES = "context=\xrefitem context \"Thread Safety\" \"Thread Safety\"" > +ALIASES += "threadbound=\ref thread-bound \"thread-bound\"" > +ALIASES += "threadsafe=\ref thread-safe \"thread-safe\"" > > # This tag can be used to specify a number of word-keyword mappings (TCL only). > # A mapping has the form "name=value". For example adding "class=itcl::class" > diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp > index fe32cd677596..c1698d469a6c 100644 > --- a/src/libcamera/thread.cpp > +++ b/src/libcamera/thread.cpp > @@ -19,6 +19,88 @@ > #include "log.h" > #include "message.h" > > +/** > + * \page thread Thread Support > + * > + * libcamera supports multi-threaded applications through a threading model that > + * sets precise rules to guarantee thread-safe usage of the API. Additionally, > + * libcamera makes internal use of threads, and offers APIs that simplify > + * interactions with application threads. Careful compliance with the threading > + * model will ensure avoidance of race conditions. > + * > + * \section thread-reentrancy Reentrancy and Thread-Safety > + * > + * Through the documentation, several terms are used to define how classes and > + * their member functions can be used from multiple threads. > + * > + * - A **reentrant** function may be called simultaneously from multiple > + * threads if and only if each invocation uses a different instance of the > + * class. This is the default for all member functions not explictly marked > + * otherwise. > + * > + * - \anchor thread-safe A **thread-safe** function may be called > + * simultaneously from multiple threads on the same instance of a class. A > + * thread-safe function is thus reentrant. > + * > + * - \anchor thread-bound A **thread-bound** function may be called only from > + * the thread that the class instances lives in (see section \ref > + * thread-objects). For instances of classes that do not derive from the > + * Object class, this is the thread in which the instance was created. A > + * thread-bound function is not thread-safe, and may or may not be reentrant. > + * > + * Neither reentrancy nor thread-safety, in this context, mean that a function > + * may be called simultaneously from the same thread, for instance from a > + * callback invoked by the the function. This may deadlock and isn't allowed s/the the/the > + * unless separately documented. > + * > + * A class is defined as reentrant, thread-safe or thread-bound if all its > + * member functions are reentrant, thread-safe or thread-bound respectively. > + * Some member functions may additionally be documented as having additional > + * thread-related attributes. > + * > + * Most classes are reentrant but not thread-safe, as making them fully > + * thread-safe would incur locking costs considered prohibitive for the > + * expected use cases. > + * > + * \section thread-objects Threads and Objects > + * > + * Instances of the Object class and all its derived classes are thread-aware > + * and are bound to the thread they are created in. They are said to *live* in > + * a thread, and they interact with the event loop of their thread for the > + * purpose of message passing and signal delivery. Messages posted to the > + * object with Object::postMessage() will be delivered from the event loop of > + * the thread that the object lives in. Signals delivered to the object, unless > + * explicitly connected with ConnectionTypeDirect, will also be delivered from > + * the object thread's event loop. > + * > + * All Object instances created by libcamera are bound to an internal thread, > + * an applications don't need to provide an event loop to support them. Object > + * instances created by applications require an event loop. It is the > + * responsibility of applications to provide that event loop, either explicitly > + * through CameraManager::setEventDispatcher(), or by running the default event > + * loop provided by CameraManager::eventDispatcher() in their main thread. The > + * main thread of an application is the one that calls CameraManager::start(). This is all good, but I would move this before the thread-safety part.. Apart from that Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Thanks j > + * > + * \section thread-signals Threads and Signals > + * > + * When sent to a receiver that does not inherit from the Object class, signals > + * are delivered synchronously in the thread of the sender. When the receiver > + * inherits from the Object class, delivery is by default asynchronous if the > + * sender and receiver live in different threads. In that case, the signal is > + * posted to the receiver's message queue and will be delivered from the > + * receiver's event loop, running in the receiver's thread. This mechanism can > + * be overridden by selecting a different connection type when calling > + * Signal::connect(). > + * > + * Asynchronous signal delivery is used internally in libcamera, but is also > + * available to applications if desired. To use this feature, applications > + * shall create receiver classes that inherit from the Object class, and > + * provide an event loop to the CameraManager as explained above. Note that > + * Object instance created by the application are limited to living in the > + * application's main thread. Creating Object instances from another thread of > + * an application causes undefined behaviour. > + */ > + > /** > * \file thread.h > * \brief Thread support > -- > Regards, > > Laurent Pinchart > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel
Hi Laurent, Thanks for this grate write up. On 2020-01-20 02:24:28 +0200, Laurent Pinchart wrote: > Document the design of libcamera's threading support, and prepare to > document thread-safety of classes and functions with a doxygen alias > command. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> > --- > Documentation/Doxyfile.in | 4 +- > src/libcamera/thread.cpp | 82 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in > index 8e6fbdbb92b6..734672ed15dc 100644 > --- a/Documentation/Doxyfile.in > +++ b/Documentation/Doxyfile.in > @@ -239,7 +239,9 @@ TAB_SIZE = 4 > # newlines (in the resulting output). You can put ^^ in the value part of an > # alias to insert a newline as if a physical newline was in the original file. > > -ALIASES = > +ALIASES = "context=\xrefitem context \"Thread Safety\" \"Thread Safety\"" > +ALIASES += "threadbound=\ref thread-bound \"thread-bound\"" > +ALIASES += "threadsafe=\ref thread-safe \"thread-safe\"" > > # This tag can be used to specify a number of word-keyword mappings (TCL only). > # A mapping has the form "name=value". For example adding "class=itcl::class" > diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp > index fe32cd677596..c1698d469a6c 100644 > --- a/src/libcamera/thread.cpp > +++ b/src/libcamera/thread.cpp > @@ -19,6 +19,88 @@ > #include "log.h" > #include "message.h" > > +/** > + * \page thread Thread Support > + * > + * libcamera supports multi-threaded applications through a threading model that > + * sets precise rules to guarantee thread-safe usage of the API. Additionally, > + * libcamera makes internal use of threads, and offers APIs that simplify > + * interactions with application threads. Careful compliance with the threading > + * model will ensure avoidance of race conditions. > + * > + * \section thread-reentrancy Reentrancy and Thread-Safety > + * > + * Through the documentation, several terms are used to define how classes and > + * their member functions can be used from multiple threads. > + * > + * - A **reentrant** function may be called simultaneously from multiple > + * threads if and only if each invocation uses a different instance of the > + * class. This is the default for all member functions not explictly marked > + * otherwise. > + * > + * - \anchor thread-safe A **thread-safe** function may be called > + * simultaneously from multiple threads on the same instance of a class. A > + * thread-safe function is thus reentrant. > + * > + * - \anchor thread-bound A **thread-bound** function may be called only from > + * the thread that the class instances lives in (see section \ref > + * thread-objects). For instances of classes that do not derive from the > + * Object class, this is the thread in which the instance was created. A > + * thread-bound function is not thread-safe, and may or may not be reentrant. > + * > + * Neither reentrancy nor thread-safety, in this context, mean that a function > + * may be called simultaneously from the same thread, for instance from a > + * callback invoked by the the function. This may deadlock and isn't allowed > + * unless separately documented. > + * > + * A class is defined as reentrant, thread-safe or thread-bound if all its > + * member functions are reentrant, thread-safe or thread-bound respectively. > + * Some member functions may additionally be documented as having additional > + * thread-related attributes. > + * > + * Most classes are reentrant but not thread-safe, as making them fully > + * thread-safe would incur locking costs considered prohibitive for the > + * expected use cases. > + * > + * \section thread-objects Threads and Objects > + * > + * Instances of the Object class and all its derived classes are thread-aware > + * and are bound to the thread they are created in. They are said to *live* in > + * a thread, and they interact with the event loop of their thread for the > + * purpose of message passing and signal delivery. Messages posted to the > + * object with Object::postMessage() will be delivered from the event loop of > + * the thread that the object lives in. Signals delivered to the object, unless > + * explicitly connected with ConnectionTypeDirect, will also be delivered from > + * the object thread's event loop. > + * > + * All Object instances created by libcamera are bound to an internal thread, > + * an applications don't need to provide an event loop to support them. Object > + * instances created by applications require an event loop. It is the > + * responsibility of applications to provide that event loop, either explicitly > + * through CameraManager::setEventDispatcher(), or by running the default event > + * loop provided by CameraManager::eventDispatcher() in their main thread. The > + * main thread of an application is the one that calls CameraManager::start(). > + * > + * \section thread-signals Threads and Signals > + * > + * When sent to a receiver that does not inherit from the Object class, signals > + * are delivered synchronously in the thread of the sender. When the receiver > + * inherits from the Object class, delivery is by default asynchronous if the > + * sender and receiver live in different threads. In that case, the signal is > + * posted to the receiver's message queue and will be delivered from the > + * receiver's event loop, running in the receiver's thread. This mechanism can > + * be overridden by selecting a different connection type when calling > + * Signal::connect(). > + * > + * Asynchronous signal delivery is used internally in libcamera, but is also > + * available to applications if desired. To use this feature, applications > + * shall create receiver classes that inherit from the Object class, and > + * provide an event loop to the CameraManager as explained above. Note that > + * Object instance created by the application are limited to living in the > + * application's main thread. Creating Object instances from another thread of > + * an application causes undefined behaviour. > + */ > + > /** > * \file thread.h > * \brief Thread support > -- > Regards, > > Laurent Pinchart > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel
Hi Laurent, On 20/01/2020 00:24, Laurent Pinchart wrote: > Document the design of libcamera's threading support, and prepare to > document thread-safety of classes and functions with a doxygen alias > command. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Minors below, but certainly a good write up. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > --- > Documentation/Doxyfile.in | 4 +- > src/libcamera/thread.cpp | 82 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in > index 8e6fbdbb92b6..734672ed15dc 100644 > --- a/Documentation/Doxyfile.in > +++ b/Documentation/Doxyfile.in > @@ -239,7 +239,9 @@ TAB_SIZE = 4 > # newlines (in the resulting output). You can put ^^ in the value part of an > # alias to insert a newline as if a physical newline was in the original file. > > -ALIASES = > +ALIASES = "context=\xrefitem context \"Thread Safety\" \"Thread Safety\"" > +ALIASES += "threadbound=\ref thread-bound \"thread-bound\"" > +ALIASES += "threadsafe=\ref thread-safe \"thread-safe\"" > > # This tag can be used to specify a number of word-keyword mappings (TCL only). > # A mapping has the form "name=value". For example adding "class=itcl::class" > diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp > index fe32cd677596..c1698d469a6c 100644 > --- a/src/libcamera/thread.cpp > +++ b/src/libcamera/thread.cpp > @@ -19,6 +19,88 @@ > #include "log.h" > #include "message.h" > > +/** > + * \page thread Thread Support > + * > + * libcamera supports multi-threaded applications through a threading model that > + * sets precise rules to guarantee thread-safe usage of the API. Additionally, > + * libcamera makes internal use of threads, and offers APIs that simplify > + * interactions with application threads. Careful compliance with the threading > + * model will ensure avoidance of race conditions. > + * > + * \section thread-reentrancy Reentrancy and Thread-Safety > + * > + * Through the documentation, several terms are used to define how classes and > + * their member functions can be used from multiple threads. > + * > + * - A **reentrant** function may be called simultaneously from multiple > + * threads if and only if each invocation uses a different instance of the > + * class. This is the default for all member functions not explictly marked > + * otherwise. > + * > + * - \anchor thread-safe A **thread-safe** function may be called > + * simultaneously from multiple threads on the same instance of a class. A > + * thread-safe function is thus reentrant. > + * > + * - \anchor thread-bound A **thread-bound** function may be called only from > + * the thread that the class instances lives in (see section \ref > + * thread-objects). For instances of classes that do not derive from the > + * Object class, this is the thread in which the instance was created. A > + * thread-bound function is not thread-safe, and may or may not be reentrant. > + * > + * Neither reentrancy nor thread-safety, in this context, mean that a function > + * may be called simultaneously from the same thread, for instance from a > + * callback invoked by the the function. This may deadlock and isn't allowed > + * unless separately documented. > + * > + * A class is defined as reentrant, thread-safe or thread-bound if all its > + * member functions are reentrant, thread-safe or thread-bound respectively. > + * Some member functions may additionally be documented as having additional > + * thread-related attributes. > + * > + * Most classes are reentrant but not thread-safe, as making them fully > + * thread-safe would incur locking costs considered prohibitive for the > + * expected use cases. > + * > + * \section thread-objects Threads and Objects > + * > + * Instances of the Object class and all its derived classes are thread-aware > + * and are bound to the thread they are created in. They are said to *live* in > + * a thread, and they interact with the event loop of their thread for the > + * purpose of message passing and signal delivery. Messages posted to the > + * object with Object::postMessage() will be delivered from the event loop of > + * the thread that the object lives in. Signals delivered to the object, unless > + * explicitly connected with ConnectionTypeDirect, will also be delivered from > + * the object thread's event loop. > + * > + * All Object instances created by libcamera are bound to an internal thread, > + * an applications don't need to provide an event loop to support them. Object s/* an applications/* and applications/ > + * instances created by applications require an event loop. It is the > + * responsibility of applications to provide that event loop, either explicitly > + * through CameraManager::setEventDispatcher(), or by running the default event > + * loop provided by CameraManager::eventDispatcher() in their main thread. The > + * main thread of an application is the one that calls CameraManager::start(). > + * > + * \section thread-signals Threads and Signals > + * > + * When sent to a receiver that does not inherit from the Object class, signals > + * are delivered synchronously in the thread of the sender. When the receiver > + * inherits from the Object class, delivery is by default asynchronous if the > + * sender and receiver live in different threads. In that case, the signal is > + * posted to the receiver's message queue and will be delivered from the > + * receiver's event loop, running in the receiver's thread. This mechanism can > + * be overridden by selecting a different connection type when calling > + * Signal::connect(). > + * > + * Asynchronous signal delivery is used internally in libcamera, but is also > + * available to applications if desired. To use this feature, applications > + * shall create receiver classes that inherit from the Object class, and > + * provide an event loop to the CameraManager as explained above. Note that > + * Object instance created by the application are limited to living in the s/instance/instances/ > + * application's main thread. Creating Object instances from another thread of > + * an application causes undefined behaviour. > + */ > + > /** > * \file thread.h > * \brief Thread support >
diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 8e6fbdbb92b6..734672ed15dc 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -239,7 +239,9 @@ TAB_SIZE = 4 # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. -ALIASES = +ALIASES = "context=\xrefitem context \"Thread Safety\" \"Thread Safety\"" +ALIASES += "threadbound=\ref thread-bound \"thread-bound\"" +ALIASES += "threadsafe=\ref thread-safe \"thread-safe\"" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp index fe32cd677596..c1698d469a6c 100644 --- a/src/libcamera/thread.cpp +++ b/src/libcamera/thread.cpp @@ -19,6 +19,88 @@ #include "log.h" #include "message.h" +/** + * \page thread Thread Support + * + * libcamera supports multi-threaded applications through a threading model that + * sets precise rules to guarantee thread-safe usage of the API. Additionally, + * libcamera makes internal use of threads, and offers APIs that simplify + * interactions with application threads. Careful compliance with the threading + * model will ensure avoidance of race conditions. + * + * \section thread-reentrancy Reentrancy and Thread-Safety + * + * Through the documentation, several terms are used to define how classes and + * their member functions can be used from multiple threads. + * + * - A **reentrant** function may be called simultaneously from multiple + * threads if and only if each invocation uses a different instance of the + * class. This is the default for all member functions not explictly marked + * otherwise. + * + * - \anchor thread-safe A **thread-safe** function may be called + * simultaneously from multiple threads on the same instance of a class. A + * thread-safe function is thus reentrant. + * + * - \anchor thread-bound A **thread-bound** function may be called only from + * the thread that the class instances lives in (see section \ref + * thread-objects). For instances of classes that do not derive from the + * Object class, this is the thread in which the instance was created. A + * thread-bound function is not thread-safe, and may or may not be reentrant. + * + * Neither reentrancy nor thread-safety, in this context, mean that a function + * may be called simultaneously from the same thread, for instance from a + * callback invoked by the the function. This may deadlock and isn't allowed + * unless separately documented. + * + * A class is defined as reentrant, thread-safe or thread-bound if all its + * member functions are reentrant, thread-safe or thread-bound respectively. + * Some member functions may additionally be documented as having additional + * thread-related attributes. + * + * Most classes are reentrant but not thread-safe, as making them fully + * thread-safe would incur locking costs considered prohibitive for the + * expected use cases. + * + * \section thread-objects Threads and Objects + * + * Instances of the Object class and all its derived classes are thread-aware + * and are bound to the thread they are created in. They are said to *live* in + * a thread, and they interact with the event loop of their thread for the + * purpose of message passing and signal delivery. Messages posted to the + * object with Object::postMessage() will be delivered from the event loop of + * the thread that the object lives in. Signals delivered to the object, unless + * explicitly connected with ConnectionTypeDirect, will also be delivered from + * the object thread's event loop. + * + * All Object instances created by libcamera are bound to an internal thread, + * an applications don't need to provide an event loop to support them. Object + * instances created by applications require an event loop. It is the + * responsibility of applications to provide that event loop, either explicitly + * through CameraManager::setEventDispatcher(), or by running the default event + * loop provided by CameraManager::eventDispatcher() in their main thread. The + * main thread of an application is the one that calls CameraManager::start(). + * + * \section thread-signals Threads and Signals + * + * When sent to a receiver that does not inherit from the Object class, signals + * are delivered synchronously in the thread of the sender. When the receiver + * inherits from the Object class, delivery is by default asynchronous if the + * sender and receiver live in different threads. In that case, the signal is + * posted to the receiver's message queue and will be delivered from the + * receiver's event loop, running in the receiver's thread. This mechanism can + * be overridden by selecting a different connection type when calling + * Signal::connect(). + * + * Asynchronous signal delivery is used internally in libcamera, but is also + * available to applications if desired. To use this feature, applications + * shall create receiver classes that inherit from the Object class, and + * provide an event loop to the CameraManager as explained above. Note that + * Object instance created by the application are limited to living in the + * application's main thread. Creating Object instances from another thread of + * an application causes undefined behaviour. + */ + /** * \file thread.h * \brief Thread support
Document the design of libcamera's threading support, and prepare to document thread-safety of classes and functions with a doxygen alias command. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- Documentation/Doxyfile.in | 4 +- src/libcamera/thread.cpp | 82 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-)