[{"id":3544,"web_url":"https://patchwork.libcamera.org/comment/3544/","msgid":"<20200120150231.zhme5r4lpgtnfqfz@uno.localdomain>","date":"2020-01-20T15:02:31","subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Mon, Jan 20, 2020 at 02:24:30AM +0200, Laurent Pinchart wrote:\n> Make the signal connection and disconnection thread-safe, and document\n> them as such. This is required to make objects connectable from\n> different threads.\n>\n> The connect(), disconnect() and emit() methods are now all protected by\n> a global mutex, which may generate a high lock contention. This could be\n> improved with finer-grained locks or with a pool of mutexes.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/libcamera/signal.cpp | 33 +++++++++++++++++++++++++++++++++\n>  1 file changed, 33 insertions(+)\n>\n> diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp\n> index 9bb7eca8ed6e..6eab1fa74d42 100644\n> --- a/src/libcamera/signal.cpp\n> +++ b/src/libcamera/signal.cpp\n> @@ -7,6 +7,8 @@\n>\n>  #include <libcamera/signal.h>\n>\n> +#include \"thread.h\"\n> +\n\nIsn't it weird we need to include thread.h to access MutexLocker ?\n\nAnyway,\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n>  /**\n>   * \\file signal.h\n>   * \\brief Signal & slot implementation\n> @@ -14,8 +16,21 @@\n>\n>  namespace libcamera {\n>\n> +namespace {\n> +\n> +/*\n> + * Mutex to protect the SignalBase::slots_ and Object::signals_ lists. If lock\n> + * contention needs to be decreased, this could be replaced with locks in\n> + * Object and SignalBase, or with a mutex pool.\n> + */\n> +Mutex signalsLock;\n> +\n> +} /* namespace */\n> +\n>  void SignalBase::connect(BoundMethodBase *slot)\n>  {\n> +\tMutexLocker locker(signalsLock);\n> +\n>  \tObject *object = slot->object();\n>  \tif (object)\n>  \t\tobject->connect(this);\n> @@ -31,6 +46,8 @@ void SignalBase::disconnect(Object *object)\n>\n>  void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n>  {\n> +\tMutexLocker locker(signalsLock);\n> +\n>  \tfor (auto iter = slots_.begin(); iter != slots_.end(); ) {\n>  \t\tif (match(iter)) {\n>  \t\t\tObject *object = (*iter)->object();\n> @@ -47,6 +64,7 @@ void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n>\n>  SignalBase::SlotList SignalBase::slots()\n>  {\n> +\tMutexLocker locker(signalsLock);\n>  \treturn slots_;\n>  }\n>\n> @@ -99,23 +117,31 @@ SignalBase::SlotList SignalBase::slots()\n>   * disconnected from the \\a func slot of \\a object when \\a object is destroyed.\n>   * Otherwise the caller shall disconnect signals manually before destroying \\a\n>   * object.\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n>   * \\fn Signal::connect(R (*func)(Args...))\n>   * \\brief Connect the signal to a static function slot\n>   * \\param[in] func The slot static function\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n>   * \\fn Signal::disconnect()\n>   * \\brief Disconnect the signal from all slots\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n>   * \\fn Signal::disconnect(T *object)\n>   * \\brief Disconnect the signal from all slots of the \\a object\n>   * \\param[in] object The object pointer whose slots to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n> @@ -123,12 +149,16 @@ SignalBase::SlotList SignalBase::slots()\n>   * \\brief Disconnect the signal from the \\a object slot member function \\a func\n>   * \\param[in] object The object pointer whose slots to disconnect\n>   * \\param[in] func The slot member function to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n>   * \\fn Signal::disconnect(R (*func)(Args...))\n>   * \\brief Disconnect the signal from the slot static function \\a func\n>   * \\param[in] func The slot static function to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>\n>  /**\n> @@ -141,6 +171,9 @@ SignalBase::SlotList SignalBase::slots()\n>   * function are passed to the slot functions unchanged. If a slot modifies one\n>   * of the arguments (when passed by pointer or reference), the modification is\n>   * thus visible to all subsequently called slots.\n> + *\n> + * This function is not \\threadsafe, but thread-safety is guaranteed against\n> + * concurrent connect() and disconnect() calls.\n>   */\n>\n>  } /* namespace libcamera */\n> --\n> Regards,\n>\n> Laurent Pinchart\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[217.70.183.196])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5CD7C60804\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 20 Jan 2020 16:00:00 +0100 (CET)","from uno.localdomain (93-34-114-233.ip49.fastwebnet.it\n\t[93.34.114.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay4-d.mail.gandi.net (Postfix) with ESMTPSA id DAC85E0009;\n\tMon, 20 Jan 2020 14:59:59 +0000 (UTC)"],"X-Originating-IP":"93.34.114.233","Date":"Mon, 20 Jan 2020 16:02:31 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200120150231.zhme5r4lpgtnfqfz@uno.localdomain>","References":"<20200120002437.6633-1-laurent.pinchart@ideasonboard.com>\n\t<20200120002437.6633-13-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"rzh6jun4hdumgf4k\"","Content-Disposition":"inline","In-Reply-To":"<20200120002437.6633-13-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","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>","X-List-Received-Date":"Mon, 20 Jan 2020 15:00:00 -0000"}},{"id":3555,"web_url":"https://patchwork.libcamera.org/comment/3555/","msgid":"<20200120174932.GO20122@pendragon.ideasonboard.com>","date":"2020-01-20T17:49:32","subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Mon, Jan 20, 2020 at 04:02:31PM +0100, Jacopo Mondi wrote:\n> On Mon, Jan 20, 2020 at 02:24:30AM +0200, Laurent Pinchart wrote:\n> > Make the signal connection and disconnection thread-safe, and document\n> > them as such. This is required to make objects connectable from\n> > different threads.\n> >\n> > The connect(), disconnect() and emit() methods are now all protected by\n> > a global mutex, which may generate a high lock contention. This could be\n> > improved with finer-grained locks or with a pool of mutexes.\n> >\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/libcamera/signal.cpp | 33 +++++++++++++++++++++++++++++++++\n> >  1 file changed, 33 insertions(+)\n> >\n> > diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp\n> > index 9bb7eca8ed6e..6eab1fa74d42 100644\n> > --- a/src/libcamera/signal.cpp\n> > +++ b/src/libcamera/signal.cpp\n> > @@ -7,6 +7,8 @@\n> >\n> >  #include <libcamera/signal.h>\n> >\n> > +#include \"thread.h\"\n> > +\n> \n> Isn't it weird we need to include thread.h to access MutexLocker ?\n\nWe could move that to a separate file, but it's so small that I didn't\nthink it was worth when I added it. Mutexes are useless without threads\nanyway.\n\n> Anyway,\n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n> \n> >  /**\n> >   * \\file signal.h\n> >   * \\brief Signal & slot implementation\n> > @@ -14,8 +16,21 @@\n> >\n> >  namespace libcamera {\n> >\n> > +namespace {\n> > +\n> > +/*\n> > + * Mutex to protect the SignalBase::slots_ and Object::signals_ lists. If lock\n> > + * contention needs to be decreased, this could be replaced with locks in\n> > + * Object and SignalBase, or with a mutex pool.\n> > + */\n> > +Mutex signalsLock;\n> > +\n> > +} /* namespace */\n> > +\n> >  void SignalBase::connect(BoundMethodBase *slot)\n> >  {\n> > +\tMutexLocker locker(signalsLock);\n> > +\n> >  \tObject *object = slot->object();\n> >  \tif (object)\n> >  \t\tobject->connect(this);\n> > @@ -31,6 +46,8 @@ void SignalBase::disconnect(Object *object)\n> >\n> >  void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n> >  {\n> > +\tMutexLocker locker(signalsLock);\n> > +\n> >  \tfor (auto iter = slots_.begin(); iter != slots_.end(); ) {\n> >  \t\tif (match(iter)) {\n> >  \t\t\tObject *object = (*iter)->object();\n> > @@ -47,6 +64,7 @@ void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n> >\n> >  SignalBase::SlotList SignalBase::slots()\n> >  {\n> > +\tMutexLocker locker(signalsLock);\n> >  \treturn slots_;\n> >  }\n> >\n> > @@ -99,23 +117,31 @@ SignalBase::SlotList SignalBase::slots()\n> >   * disconnected from the \\a func slot of \\a object when \\a object is destroyed.\n> >   * Otherwise the caller shall disconnect signals manually before destroying \\a\n> >   * object.\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> >   * \\fn Signal::connect(R (*func)(Args...))\n> >   * \\brief Connect the signal to a static function slot\n> >   * \\param[in] func The slot static function\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> >   * \\fn Signal::disconnect()\n> >   * \\brief Disconnect the signal from all slots\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> >   * \\fn Signal::disconnect(T *object)\n> >   * \\brief Disconnect the signal from all slots of the \\a object\n> >   * \\param[in] object The object pointer whose slots to disconnect\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> > @@ -123,12 +149,16 @@ SignalBase::SlotList SignalBase::slots()\n> >   * \\brief Disconnect the signal from the \\a object slot member function \\a func\n> >   * \\param[in] object The object pointer whose slots to disconnect\n> >   * \\param[in] func The slot member function to disconnect\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> >   * \\fn Signal::disconnect(R (*func)(Args...))\n> >   * \\brief Disconnect the signal from the slot static function \\a func\n> >   * \\param[in] func The slot static function to disconnect\n> > + *\n> > + * \\context This function is \\threadsafe.\n> >   */\n> >\n> >  /**\n> > @@ -141,6 +171,9 @@ SignalBase::SlotList SignalBase::slots()\n> >   * function are passed to the slot functions unchanged. If a slot modifies one\n> >   * of the arguments (when passed by pointer or reference), the modification is\n> >   * thus visible to all subsequently called slots.\n> > + *\n> > + * This function is not \\threadsafe, but thread-safety is guaranteed against\n> > + * concurrent connect() and disconnect() calls.\n> >   */\n> >\n> >  } /* namespace libcamera */\n> > --\n> > Regards,\n> >\n> > Laurent Pinchart\n> >\n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4454760455\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 20 Jan 2020 18:49:33 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DAFFFA62;\n\tMon, 20 Jan 2020 18:49:32 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1579542573;\n\tbh=9XWX19tDHKsfp4+yZaCK/PVRnWydcwLqfr3ALBCF9D8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=T1AdClHiXKFZtiZt9XrxICJZfXDEnnPw3n1krq4UdS5l9pafbXlZiFSfdR6UWF1Rr\n\tDg6nPaccHKdzSaiX4AxyioCBGArR8C6Gy1spogzzPjBXYC9m/7jerQCXw3TW6pkpBx\n\tAM0MVPFV1aROcdNOunad1oDjHQn8hCeLXjPCIRHY=","Date":"Mon, 20 Jan 2020 19:49:32 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200120174932.GO20122@pendragon.ideasonboard.com>","References":"<20200120002437.6633-1-laurent.pinchart@ideasonboard.com>\n\t<20200120002437.6633-13-laurent.pinchart@ideasonboard.com>\n\t<20200120150231.zhme5r4lpgtnfqfz@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20200120150231.zhme5r4lpgtnfqfz@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","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>","X-List-Received-Date":"Mon, 20 Jan 2020 17:49:33 -0000"}},{"id":3574,"web_url":"https://patchwork.libcamera.org/comment/3574/","msgid":"<20200122155513.GT1124294@oden.dyn.berto.se>","date":"2020-01-22T15:55:13","subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nThanks for your work.\n\nOn 2020-01-20 02:24:30 +0200, Laurent Pinchart wrote:\n> Make the signal connection and disconnection thread-safe, and document\n> them as such. This is required to make objects connectable from\n> different threads.\n> \n> The connect(), disconnect() and emit() methods are now all protected by\n> a global mutex, which may generate a high lock contention. This could be\n> improved with finer-grained locks or with a pool of mutexes.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\n> ---\n>  src/libcamera/signal.cpp | 33 +++++++++++++++++++++++++++++++++\n>  1 file changed, 33 insertions(+)\n> \n> diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp\n> index 9bb7eca8ed6e..6eab1fa74d42 100644\n> --- a/src/libcamera/signal.cpp\n> +++ b/src/libcamera/signal.cpp\n> @@ -7,6 +7,8 @@\n>  \n>  #include <libcamera/signal.h>\n>  \n> +#include \"thread.h\"\n> +\n>  /**\n>   * \\file signal.h\n>   * \\brief Signal & slot implementation\n> @@ -14,8 +16,21 @@\n>  \n>  namespace libcamera {\n>  \n> +namespace {\n> +\n> +/*\n> + * Mutex to protect the SignalBase::slots_ and Object::signals_ lists. If lock\n> + * contention needs to be decreased, this could be replaced with locks in\n> + * Object and SignalBase, or with a mutex pool.\n> + */\n> +Mutex signalsLock;\n> +\n> +} /* namespace */\n> +\n>  void SignalBase::connect(BoundMethodBase *slot)\n>  {\n> +\tMutexLocker locker(signalsLock);\n> +\n>  \tObject *object = slot->object();\n>  \tif (object)\n>  \t\tobject->connect(this);\n> @@ -31,6 +46,8 @@ void SignalBase::disconnect(Object *object)\n>  \n>  void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n>  {\n> +\tMutexLocker locker(signalsLock);\n> +\n>  \tfor (auto iter = slots_.begin(); iter != slots_.end(); ) {\n>  \t\tif (match(iter)) {\n>  \t\t\tObject *object = (*iter)->object();\n> @@ -47,6 +64,7 @@ void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)\n>  \n>  SignalBase::SlotList SignalBase::slots()\n>  {\n> +\tMutexLocker locker(signalsLock);\n>  \treturn slots_;\n>  }\n>  \n> @@ -99,23 +117,31 @@ SignalBase::SlotList SignalBase::slots()\n>   * disconnected from the \\a func slot of \\a object when \\a object is destroyed.\n>   * Otherwise the caller shall disconnect signals manually before destroying \\a\n>   * object.\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n>   * \\fn Signal::connect(R (*func)(Args...))\n>   * \\brief Connect the signal to a static function slot\n>   * \\param[in] func The slot static function\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n>   * \\fn Signal::disconnect()\n>   * \\brief Disconnect the signal from all slots\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n>   * \\fn Signal::disconnect(T *object)\n>   * \\brief Disconnect the signal from all slots of the \\a object\n>   * \\param[in] object The object pointer whose slots to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n> @@ -123,12 +149,16 @@ SignalBase::SlotList SignalBase::slots()\n>   * \\brief Disconnect the signal from the \\a object slot member function \\a func\n>   * \\param[in] object The object pointer whose slots to disconnect\n>   * \\param[in] func The slot member function to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n>   * \\fn Signal::disconnect(R (*func)(Args...))\n>   * \\brief Disconnect the signal from the slot static function \\a func\n>   * \\param[in] func The slot static function to disconnect\n> + *\n> + * \\context This function is \\threadsafe.\n>   */\n>  \n>  /**\n> @@ -141,6 +171,9 @@ SignalBase::SlotList SignalBase::slots()\n>   * function are passed to the slot functions unchanged. If a slot modifies one\n>   * of the arguments (when passed by pointer or reference), the modification is\n>   * thus visible to all subsequently called slots.\n> + *\n> + * This function is not \\threadsafe, but thread-safety is guaranteed against\n> + * concurrent connect() and disconnect() calls.\n>   */\n>  \n>  } /* namespace libcamera */\n> -- \n> Regards,\n> \n> Laurent Pinchart\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-lf1-x141.google.com (mail-lf1-x141.google.com\n\t[IPv6:2a00:1450:4864:20::141])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CD1BD607F3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Jan 2020 16:55:15 +0100 (CET)","by mail-lf1-x141.google.com with SMTP id v201so5668840lfa.11\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Jan 2020 07:55:15 -0800 (PST)","from localhost (h-93-159.A463.priv.bahnhof.se. [46.59.93.159])\n\tby smtp.gmail.com with ESMTPSA id\n\tr12sm20362230ljh.105.2020.01.22.07.55.13\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 22 Jan 2020 07:55:14 -0800 (PST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=BcTXsL6T41DO7fp3mF4+1H2HKbXQ9A4Wo477P2r+4/c=;\n\tb=U+CBxnmmYaBnsH3SBDJLrwIF/YZ80T9zHZmawtkuIxI9so+gCozQK+soHhrzUxdeEH\n\t4YCcL8dOs4+8neRa42VSgvN3sFeMmE+QwDlc4dIPAqWF8J2nvWqm2+lD2K/afo5l0jEw\n\tM7u5RJtpRS+1JqmL9yteN1O9A0AUR2HpCvTo21cS5zt21E2vDz9XdCnZfuEZILiqe5fC\n\thAl8w5z8aolYDv9uHfmvKv306bdTdIRpjsA0nlaHjmyK/dvXU19Gc6kzrL06NfVQsUNa\n\tfN3F1ONpMxQ0LE3NlvAlw6AYBfvCTFcXCMUifzvTQyIRMWEuKNJYjWI7YY++AGE+8H9z\n\thFMg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=BcTXsL6T41DO7fp3mF4+1H2HKbXQ9A4Wo477P2r+4/c=;\n\tb=F7/kA/NJ6sC3t4+Ft5wyvC/Hpn8ATnsrf3u6l8xXRpl/OFsl4U9lH3BLNVZtb2EsVF\n\t2CzMRo5ko8mtIrE3Yp88Ty/PgJHHdtCZucSJdLFccqh5tGxWeh8U1F0qdkV5mvuMXcei\n\tlOi21k1B6WcWTs5yTOIvTVV0D4FkofOSspXjX7Fxoe3ydEC7MuulE3iaU1xhLv8pFDwP\n\tK88+IZvlETWfqh3W43LqyoivJnZKleOz6T60K3e5yna297wREPK2RJZeGUPkudJqqrRv\n\tP6sksNudY2eHM6oLBGhYii+FP7HrDjC9BzLDgFDlWU/4a9K6ZzO16PRJAy2wy239vjN2\n\tHyyw==","X-Gm-Message-State":"APjAAAUxuza6koPne1jLpFngNrmdVeYEL+4RjsJdXL0HsXdJbrijunGy\n\tJOjmrkdB0oTjYQTmqkdueqwce0SEVtI=","X-Google-Smtp-Source":"APXvYqzas5WOmykmr0mNAL9VrA1PIbWdxTiSNTVOzos/RjtvTWkrsGuh3qptPkDje+j6DhmB8sO7BA==","X-Received":"by 2002:a19:cb97:: with SMTP id\n\tb145mr2136228lfg.161.1579708515139; \n\tWed, 22 Jan 2020 07:55:15 -0800 (PST)","Date":"Wed, 22 Jan 2020 16:55:13 +0100","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200122155513.GT1124294@oden.dyn.berto.se>","References":"<20200120002437.6633-1-laurent.pinchart@ideasonboard.com>\n\t<20200120002437.6633-13-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200120002437.6633-13-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 12/19] libcamera: signal: Make\n\tconnection and disconnection thread-safe","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>","X-List-Received-Date":"Wed, 22 Jan 2020 15:55:16 -0000"}}]