[{"id":19844,"web_url":"https://patchwork.libcamera.org/comment/19844/","msgid":"<3e86c82b-cbfd-735c-216f-7785998b5147@ideasonboard.com>","date":"2021-09-24T19:41:00","subject":"Re: [libcamera-devel] [PATCH v3 5/5] libcamera: control_serializer:\n\tSeparate the handles space","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Jacopo\n\nOn 24/09/2021 18:25, Jacopo Mondi wrote:\n> Two indipendnt instancess of the ControlSerializer class are in use at\n\ns/indipendnt instancess/independent instances/\n\n> the IPC boundaries, one in the Proxy class that serializes data from the\n> pipeline handler to the IPA, and one in the ProxyWorker which serializes\n> data in the opposite direction.\n> \n> Each instance operates autonomously, without any centralized point of\n> control, and each one assigns a numerical handle to each ControlInfoMap\n> it serializes. This creates a risk of potential collision on the handle\n> values, as both instances will use the same numerical space and\n> are not aware of what handles has been already used by the instance \"on\n> the other side\".\n> \n> To fix that, partition the handles numerical space by initializing the\n> control serializer with a seed according to the role of the component\n> that creates the serializer and increment the handle number by 2, to\n> avoid any collision risk.\n> \n> While this is temporary and rather hacky solution, it solves an issue\n\nCareful ... it might not be temporary ... ;-)\n\n> with isolated IPA modules without too much complexity added.\n> \n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n> ---\n>  .../libcamera/internal/control_serializer.h   |  8 ++-\n>  src/libcamera/control_serializer.cpp          | 63 +++++++++++++++++--\n>  test/serialization/control_serialization.cpp  |  4 +-\n>  .../ipa_data_serializer_test.cpp              |  6 +-\n>  .../module_ipa_proxy.cpp.tmpl                 |  3 +-\n>  .../module_ipa_proxy_worker.cpp.tmpl          |  4 +-\n>  6 files changed, 75 insertions(+), 13 deletions(-)\n> \n> diff --git a/include/libcamera/internal/control_serializer.h b/include/libcamera/internal/control_serializer.h\n> index 8a66be324138..caeafa11bc54 100644\n> --- a/include/libcamera/internal/control_serializer.h\n> +++ b/include/libcamera/internal/control_serializer.h\n> @@ -20,7 +20,12 @@ class ByteStreamBuffer;\n>  class ControlSerializer\n>  {\n>  public:\n> -\tControlSerializer();\n> +\tenum class Role {\n> +\t\tProxy,\n> +\t\tWorker\n> +\t};\n> +\n> +\tControlSerializer(Role role);\n>  \n>  \tvoid reset();\n>  \n> @@ -47,6 +52,7 @@ private:\n>  \tControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer);\n>  \n>  \tunsigned int serial_;\n> +\tunsigned int serialSeed_;\n>  \tstd::vector<std::unique_ptr<ControlId>> controlIds_;\n>  \tstd::vector<std::unique_ptr<ControlIdMap>> controlIdMaps_;\n>  \tstd::map<unsigned int, ControlInfoMap> infoMaps_;\n> diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp\n> index f1245ea620ab..025222d77e4d 100644\n> --- a/src/libcamera/control_serializer.cpp\n> +++ b/src/libcamera/control_serializer.cpp\n> @@ -62,6 +62,14 @@ LOG_DEFINE_CATEGORY(Serializer)\n>   * corresponding ControlInfoMap handle in the binary data, and when\n>   * deserializing to retrieve the corresponding ControlInfoMap.\n>   *\n> + * As independent ControlSerializer instances are used on both sides of the IPC\n> + * boundary, and the two instances operate without a shared point of control,\n> + * there is a potential risk of collision of the numerical handles assigned to\n> + * each serialized ControlInfoMap. For this reason the control serializer is\n> + * initialized with a seed and the handle is incremented by 2, so that instances\n> + * initialized with a different seed operate on a separate numerical space,\n> + * avoiding any collision risk.\n> + *\n>   * In order to perform those tasks, the serializer keeps an internal state that\n>   * needs to be properly populated. This mechanism requires the ControlInfoMap\n>   * corresponding to a ControlList to have been serialized or deserialized\n> @@ -77,9 +85,45 @@ LOG_DEFINE_CATEGORY(Serializer)\n>   * proceed with care to avoid stale references.\n>   */\n>  \n> -ControlSerializer::ControlSerializer()\n> -\t: serial_(0)\n> +/**\n> + * \\enum ControlSerializer::Role\n> + * \\brief Define the role of the IPC component using the control serializer.\n> + *\n> + * The role of the component that creates the serializer is used to initialize\n> + * the handles numerical space.\n> + *\n> + * \\var ControlSerializer::Role::Proxy\n> + * \\brief The control serializer is used by the IPC Proxy classes\n> + *\n> + * \\var ControlSerializer::Role::Worker\n> + * \\brief The control serializer is used by the IPC ProxyWorker classes\n> + */\n> +\n> +/**\n> + * \\brief Construct a new ControlSerializer\n> + * \\param[in] role The role of the IPC component using the serializer\n> + */\n> +ControlSerializer::ControlSerializer(Role role)\n>  {\n> +\t/*\n> +\t * Initialize the handle numerical space using the role of the\n> +\t * component that created the instance.\n> +\t *\n> +\t * Instances initialized for a different role will use a different\n> +\t * numerical handle space, avoiding any collision risk when, in example,\n> +\t * two instances of the ControlSerializer class are used at the IPC\n> +\t * boundaries.\n> +\t *\n> +\t * Start counting handles from '1' as '0' is a special value used as\n> +\t * place holder when serializing lists that do not have a ControlInfoMap\n> +\t * associated (in example list of libcamera controls::controls).\n> +\t *\n> +\t * \\todo This is a temporary hack and should probably be better\n> +\t * engineered, but for the time being it avoid collisions on the handle\n> +\t * value when using IPC.\n> +\t */\n> +\tserialSeed_ = role == Role::Proxy ? 1 : 2;\n> +\tserial_ = serialSeed_;\n>  }\n>  \n>  /**\n> @@ -90,7 +134,7 @@ ControlSerializer::ControlSerializer()\n>   */\n>  void ControlSerializer::reset()\n>  {\n> -\tserial_ = 0;\n> +\tserial_ = serialSeed_;\n>  \n>  \tinfoMapHandles_.clear();\n>  \tinfoMaps_.clear();\n> @@ -200,10 +244,10 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,\n>  \telse\n>  \t\tidMapType = IPA_CONTROL_ID_MAP_V4L2;\n>  \n> -\t/* Prepare the packet header, assign a handle to the ControlInfoMap. */\n> +\t/* Prepare the packet header. */\n>  \tstruct ipa_controls_header hdr;\n>  \thdr.version = IPA_CONTROLS_FORMAT_VERSION;\n> -\thdr.handle = ++serial_;\n> +\thdr.handle = serial_;\n>  \thdr.entries = infoMap.size();\n>  \thdr.size = sizeof(hdr) + entriesSize + valuesSize;\n>  \thdr.data_offset = sizeof(hdr) + entriesSize;\n> @@ -211,6 +255,15 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,\n>  \n>  \tbuffer.write(&hdr);\n>  \n> +\t/*\n> +\t * Increment the handle for the ControlInfoMap by 2 to keep the handles\n> +\t * numerical space partitioned between instances initialized for a\n> +\t * different role.\n> +\t *\n> +\t * \\sa ControlSerializer::Role\n> +\t */\n> +\tserial_ += 2;\n> +\n>  \t/*\n>  \t * Serialize all entries.\n>  \t * \\todo Serialize the control name too\n> diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\n> index 5ac9c4ede5f9..a507d98a152d 100644\n> --- a/test/serialization/control_serialization.cpp\n> +++ b/test/serialization/control_serialization.cpp\n> @@ -30,8 +30,8 @@ protected:\n>  \n>  \tint run() override\n>  \t{\n> -\t\tControlSerializer serializer;\n> -\t\tControlSerializer deserializer;\n> +\t\tControlSerializer serializer(ControlSerializer::Role::Proxy);\n> +\t\tControlSerializer deserializer(ControlSerializer::Role::Worker);\n>  \n>  \t\tstd::vector<uint8_t> infoData;\n>  \t\tstd::vector<uint8_t> listData;\n> diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp\n> index eca19a6642e1..5fcdcb8eae92 100644\n> --- a/test/serialization/ipa_data_serializer_test.cpp\n> +++ b/test/serialization/ipa_data_serializer_test.cpp\n> @@ -162,7 +162,7 @@ private:\n>  \n>  \tint testControls()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\tconst ControlInfoMap &infoMap = camera_->controls();\n>  \t\tControlList list = generateControlList(infoMap);\n> @@ -195,7 +195,7 @@ private:\n>  \n>  \tint testVector()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\t/*\n>  \t\t * We don't test FileDescriptor serdes because it dup()s, so we\n> @@ -265,7 +265,7 @@ private:\n>  \n>  \tint testMap()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\t/*\n>  \t\t * Realistically, only string and integral keys.\n> diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> index aab1fffbcaf0..d856339aa9ee 100644\n> --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> @@ -46,7 +46,8 @@ namespace {{ns}} {\n>  {%- endif %}\n>  \n>  {{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate)\n> -\t: IPAProxy(ipam), isolate_(isolate), seq_(0)\n> +\t: IPAProxy(ipam), isolate_(isolate),\n> +\t  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)\n>  {\n>  \tLOG(IPAProxy, Debug)\n>  \t\t<< \"initializing {{module_name}} proxy: loading IPA from \"\n> diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> index 890246a8849b..764e7a3af63a 100644\n> --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> @@ -53,7 +53,9 @@ class {{proxy_worker_name}}\n>  {\n>  public:\n>  \t{{proxy_worker_name}}()\n> -\t\t: ipa_(nullptr), exit_(false) {}\n> +\t\t: ipa_(nullptr),\n> +\t\t  controlSerializer_(ControlSerializer::Role::Worker),\n> +\t\t  exit_(false) {}\n>  \n>  \t~{{proxy_worker_name}}() {}\n>  \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 3BD9BBDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Sep 2021 19:41:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 78E226918C;\n\tFri, 24 Sep 2021 21:41:05 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5C32E687DD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 21:41:04 +0200 (CEST)","from [192.168.0.20]\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C9F6CE52;\n\tFri, 24 Sep 2021 21:41:03 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"cPAGa1vW\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632512463;\n\tbh=LAtLIzNHGQ4Mof8wi4PZ1NLQ6+zVte4y7WhzcAC2gyQ=;\n\th=Subject:To:References:From:Date:In-Reply-To:From;\n\tb=cPAGa1vWvrlA/keY3vz/5CqROn8EwaCBN2hkKIhro4PRKJ2PbnVN5F6Eiawkh0slo\n\tzjuxcEcoE0ay34sx/k5vRE/MNEqmTDINMpIOkmx2wqmqugSJWYdAn2VaDbuWUXgCqL\n\t6z9h/N+CI/QESR4iir7dtus1jP0VVE2q8Sm7lrCA=","To":"Jacopo Mondi <jacopo@jmondi.org>, libcamera-devel@lists.libcamera.org","References":"<20210924172525.160482-1-jacopo@jmondi.org>\n\t<20210924172525.160482-6-jacopo@jmondi.org>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Message-ID":"<3e86c82b-cbfd-735c-216f-7785998b5147@ideasonboard.com>","Date":"Fri, 24 Sep 2021 20:41:00 +0100","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101\n\tThunderbird/78.13.0","MIME-Version":"1.0","In-Reply-To":"<20210924172525.160482-6-jacopo@jmondi.org>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH v3 5/5] libcamera: control_serializer:\n\tSeparate the handles space","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19847,"web_url":"https://patchwork.libcamera.org/comment/19847/","msgid":"<YVDRuuddwdlClHyy@pendragon.ideasonboard.com>","date":"2021-09-26T20:02:02","subject":"Re: [libcamera-devel] [PATCH v3 5/5] libcamera: control_serializer:\n\tSeparate the handles space","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Fri, Sep 24, 2021 at 07:25:25PM +0200, Jacopo Mondi wrote:\n> Two indipendnt instancess of the ControlSerializer class are in use at\n\n\"independent instances\"\n\n> the IPC boundaries, one in the Proxy class that serializes data from the\n> pipeline handler to the IPA, and one in the ProxyWorker which serializes\n> data in the opposite direction.\n> \n> Each instance operates autonomously, without any centralized point of\n> control, and each one assigns a numerical handle to each ControlInfoMap\n> it serializes. This creates a risk of potential collision on the handle\n> values, as both instances will use the same numerical space and\n> are not aware of what handles has been already used by the instance \"on\n> the other side\".\n> \n> To fix that, partition the handles numerical space by initializing the\n> control serializer with a seed according to the role of the component\n> that creates the serializer and increment the handle number by 2, to\n> avoid any collision risk.\n> \n> While this is temporary and rather hacky solution, it solves an issue\n> with isolated IPA modules without too much complexity added.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n> ---\n>  .../libcamera/internal/control_serializer.h   |  8 ++-\n>  src/libcamera/control_serializer.cpp          | 63 +++++++++++++++++--\n>  test/serialization/control_serialization.cpp  |  4 +-\n>  .../ipa_data_serializer_test.cpp              |  6 +-\n>  .../module_ipa_proxy.cpp.tmpl                 |  3 +-\n>  .../module_ipa_proxy_worker.cpp.tmpl          |  4 +-\n>  6 files changed, 75 insertions(+), 13 deletions(-)\n> \n> diff --git a/include/libcamera/internal/control_serializer.h b/include/libcamera/internal/control_serializer.h\n> index 8a66be324138..caeafa11bc54 100644\n> --- a/include/libcamera/internal/control_serializer.h\n> +++ b/include/libcamera/internal/control_serializer.h\n> @@ -20,7 +20,12 @@ class ByteStreamBuffer;\n>  class ControlSerializer\n>  {\n>  public:\n> -\tControlSerializer();\n> +\tenum class Role {\n> +\t\tProxy,\n> +\t\tWorker\n> +\t};\n> +\n> +\tControlSerializer(Role role);\n>  \n>  \tvoid reset();\n>  \n> @@ -47,6 +52,7 @@ private:\n>  \tControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer);\n>  \n>  \tunsigned int serial_;\n> +\tunsigned int serialSeed_;\n>  \tstd::vector<std::unique_ptr<ControlId>> controlIds_;\n>  \tstd::vector<std::unique_ptr<ControlIdMap>> controlIdMaps_;\n>  \tstd::map<unsigned int, ControlInfoMap> infoMaps_;\n> diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp\n> index f1245ea620ab..025222d77e4d 100644\n> --- a/src/libcamera/control_serializer.cpp\n> +++ b/src/libcamera/control_serializer.cpp\n> @@ -62,6 +62,14 @@ LOG_DEFINE_CATEGORY(Serializer)\n>   * corresponding ControlInfoMap handle in the binary data, and when\n>   * deserializing to retrieve the corresponding ControlInfoMap.\n>   *\n> + * As independent ControlSerializer instances are used on both sides of the IPC\n> + * boundary, and the two instances operate without a shared point of control,\n> + * there is a potential risk of collision of the numerical handles assigned to\n> + * each serialized ControlInfoMap. For this reason the control serializer is\n> + * initialized with a seed and the handle is incremented by 2, so that instances\n> + * initialized with a different seed operate on a separate numerical space,\n> + * avoiding any collision risk.\n> + *\n>   * In order to perform those tasks, the serializer keeps an internal state that\n>   * needs to be properly populated. This mechanism requires the ControlInfoMap\n>   * corresponding to a ControlList to have been serialized or deserialized\n> @@ -77,9 +85,45 @@ LOG_DEFINE_CATEGORY(Serializer)\n>   * proceed with care to avoid stale references.\n>   */\n>  \n> -ControlSerializer::ControlSerializer()\n> -\t: serial_(0)\n> +/**\n> + * \\enum ControlSerializer::Role\n> + * \\brief Define the role of the IPC component using the control serializer.\n\ns/.$//\n\n> + *\n> + * The role of the component that creates the serializer is used to initialize\n> + * the handles numerical space.\n> + *\n> + * \\var ControlSerializer::Role::Proxy\n> + * \\brief The control serializer is used by the IPC Proxy classes\n> + *\n> + * \\var ControlSerializer::Role::Worker\n> + * \\brief The control serializer is used by the IPC ProxyWorker classes\n> + */\n> +\n> +/**\n> + * \\brief Construct a new ControlSerializer\n> + * \\param[in] role The role of the IPC component using the serializer\n> + */\n> +ControlSerializer::ControlSerializer(Role role)\n>  {\n> +\t/*\n> +\t * Initialize the handle numerical space using the role of the\n> +\t * component that created the instance.\n> +\t *\n> +\t * Instances initialized for a different role will use a different\n> +\t * numerical handle space, avoiding any collision risk when, in example,\n> +\t * two instances of the ControlSerializer class are used at the IPC\n> +\t * boundaries.\n> +\t *\n> +\t * Start counting handles from '1' as '0' is a special value used as\n> +\t * place holder when serializing lists that do not have a ControlInfoMap\n> +\t * associated (in example list of libcamera controls::controls).\n> +\t *\n> +\t * \\todo This is a temporary hack and should probably be better\n> +\t * engineered, but for the time being it avoid collisions on the handle\n\ns/avoid/avoids/\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> +\t * value when using IPC.\n> +\t */\n> +\tserialSeed_ = role == Role::Proxy ? 1 : 2;\n> +\tserial_ = serialSeed_;\n>  }\n>  \n>  /**\n> @@ -90,7 +134,7 @@ ControlSerializer::ControlSerializer()\n>   */\n>  void ControlSerializer::reset()\n>  {\n> -\tserial_ = 0;\n> +\tserial_ = serialSeed_;\n>  \n>  \tinfoMapHandles_.clear();\n>  \tinfoMaps_.clear();\n> @@ -200,10 +244,10 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,\n>  \telse\n>  \t\tidMapType = IPA_CONTROL_ID_MAP_V4L2;\n>  \n> -\t/* Prepare the packet header, assign a handle to the ControlInfoMap. */\n> +\t/* Prepare the packet header. */\n>  \tstruct ipa_controls_header hdr;\n>  \thdr.version = IPA_CONTROLS_FORMAT_VERSION;\n> -\thdr.handle = ++serial_;\n> +\thdr.handle = serial_;\n>  \thdr.entries = infoMap.size();\n>  \thdr.size = sizeof(hdr) + entriesSize + valuesSize;\n>  \thdr.data_offset = sizeof(hdr) + entriesSize;\n> @@ -211,6 +255,15 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,\n>  \n>  \tbuffer.write(&hdr);\n>  \n> +\t/*\n> +\t * Increment the handle for the ControlInfoMap by 2 to keep the handles\n> +\t * numerical space partitioned between instances initialized for a\n> +\t * different role.\n> +\t *\n> +\t * \\sa ControlSerializer::Role\n> +\t */\n> +\tserial_ += 2;\n> +\n>  \t/*\n>  \t * Serialize all entries.\n>  \t * \\todo Serialize the control name too\n> diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\n> index 5ac9c4ede5f9..a507d98a152d 100644\n> --- a/test/serialization/control_serialization.cpp\n> +++ b/test/serialization/control_serialization.cpp\n> @@ -30,8 +30,8 @@ protected:\n>  \n>  \tint run() override\n>  \t{\n> -\t\tControlSerializer serializer;\n> -\t\tControlSerializer deserializer;\n> +\t\tControlSerializer serializer(ControlSerializer::Role::Proxy);\n> +\t\tControlSerializer deserializer(ControlSerializer::Role::Worker);\n>  \n>  \t\tstd::vector<uint8_t> infoData;\n>  \t\tstd::vector<uint8_t> listData;\n> diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp\n> index eca19a6642e1..5fcdcb8eae92 100644\n> --- a/test/serialization/ipa_data_serializer_test.cpp\n> +++ b/test/serialization/ipa_data_serializer_test.cpp\n> @@ -162,7 +162,7 @@ private:\n>  \n>  \tint testControls()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\tconst ControlInfoMap &infoMap = camera_->controls();\n>  \t\tControlList list = generateControlList(infoMap);\n> @@ -195,7 +195,7 @@ private:\n>  \n>  \tint testVector()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\t/*\n>  \t\t * We don't test FileDescriptor serdes because it dup()s, so we\n> @@ -265,7 +265,7 @@ private:\n>  \n>  \tint testMap()\n>  \t{\n> -\t\tControlSerializer cs;\n> +\t\tControlSerializer cs(ControlSerializer::Role::Proxy);\n>  \n>  \t\t/*\n>  \t\t * Realistically, only string and integral keys.\n> diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> index aab1fffbcaf0..d856339aa9ee 100644\n> --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n> @@ -46,7 +46,8 @@ namespace {{ns}} {\n>  {%- endif %}\n>  \n>  {{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate)\n> -\t: IPAProxy(ipam), isolate_(isolate), seq_(0)\n> +\t: IPAProxy(ipam), isolate_(isolate),\n> +\t  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)\n>  {\n>  \tLOG(IPAProxy, Debug)\n>  \t\t<< \"initializing {{module_name}} proxy: loading IPA from \"\n> diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> index 890246a8849b..764e7a3af63a 100644\n> --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> @@ -53,7 +53,9 @@ class {{proxy_worker_name}}\n>  {\n>  public:\n>  \t{{proxy_worker_name}}()\n> -\t\t: ipa_(nullptr), exit_(false) {}\n> +\t\t: ipa_(nullptr),\n> +\t\t  controlSerializer_(ControlSerializer::Role::Worker),\n> +\t\t  exit_(false) {}\n>  \n>  \t~{{proxy_worker_name}}() {}\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 C57EDBF01C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 26 Sep 2021 20:02:10 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4D72D6918E;\n\tSun, 26 Sep 2021 22:02:10 +0200 (CEST)","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 356B86012D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 26 Sep 2021 22:02:08 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9599AEF;\n\tSun, 26 Sep 2021 22:02:07 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"WmJKZsUP\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632686527;\n\tbh=vmM/+nGSvuuyAlju322hxlZK+P/ed2DcEUAUTIHxvJs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=WmJKZsUPDEb1+BQE1zbNRv3qJrG0h+JIwcIp5fIzipKp6TgLeMYt5IM2beQ6Mw9DT\n\ticfIQwRyeFUyGp0ffRqrAnIoFiHfknWa6v7TTNctiabw54bGmE+LbgFztkr+fITkES\n\tbvMrenwirlXLhHfz8p/b+wpLyedtSeFKPpQSH21g=","Date":"Sun, 26 Sep 2021 23:02:02 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<YVDRuuddwdlClHyy@pendragon.ideasonboard.com>","References":"<20210924172525.160482-1-jacopo@jmondi.org>\n\t<20210924172525.160482-6-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20210924172525.160482-6-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v3 5/5] libcamera: control_serializer:\n\tSeparate the handles space","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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]