[RFC,v1,3/7] libcamera: controls: Add rvalue `ControlList::merge()`
diff mbox series

Message ID 20250924124713.3361707-4-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • libcamera: camera: Add `applyControls()`
Related show

Commit Message

Barnabás Pőcze Sept. 24, 2025, 12:47 p.m. UTC
Add an overload of `ControlList::merge()` that takes the source `ControlList`
object via an rvalue. In contrast to the other overload, this one does not
make copies, it uses `std::unordered_map::merge()` to move key-value pairs
from one map to the other.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 include/libcamera/controls.h |  1 +
 src/libcamera/controls.cpp   | 42 +++++++++++++++++++++++++++++++++---
 2 files changed, 40 insertions(+), 3 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
index 32fb31f78..5d4a53c46 100644
--- a/include/libcamera/controls.h
+++ b/include/libcamera/controls.h
@@ -432,6 +432,7 @@  public:
 
 	void clear() { controls_.clear(); }
 	void merge(const ControlList &source, MergePolicy policy = MergePolicy::KeepExisting);
+	void merge(ControlList &&source, MergePolicy policy = MergePolicy::KeepExisting);
 
 	bool contains(unsigned int id) const;
 
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index 1e1b49e6b..54cd3b703 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -1005,9 +1005,6 @@  ControlList::ControlList(const ControlInfoMap &infoMap,
  *
  * Only control lists created from the same ControlIdMap or ControlInfoMap may
  * be merged. Attempting to do otherwise results in undefined behaviour.
- *
- * \todo Reimplement or implement an overloaded version which internally uses
- * std::unordered_map::merge() and accepts a non-const argument.
  */
 void ControlList::merge(const ControlList &source, MergePolicy policy)
 {
@@ -1035,6 +1032,45 @@  void ControlList::merge(const ControlList &source, MergePolicy policy)
 	}
 }
 
+/**
+ * \brief Merge the \a source into the ControlList
+ * \param[in] source The ControlList to merge into this object
+ * \param[in] policy Controls if existing elements in *this shall be
+ * overwritten
+ *
+ * Merging two control lists moves elements from the \a source and inserts
+ * them in *this. If the \a source contains elements whose key is already
+ * present in *this, then those elements are only overwritten if
+ * \a policy is MergePolicy::OverwriteExisting.
+ *
+ * Only control lists created from the same ControlIdMap or ControlInfoMap may
+ * be merged. Attempting to do otherwise results in undefined behaviour.
+ */
+void ControlList::merge(ControlList &&source, MergePolicy policy)
+{
+	/**
+	 * \todo ASSERT that the current and source ControlList are derived
+	 * from a compatible ControlIdMap, to prevent undefined behaviour due to
+	 * id collisions.
+	 *
+	 * This can not currently be a direct pointer comparison due to the
+	 * duplication of the ControlIdMaps in the isolated IPA use cases.
+	 * Furthermore, manually checking each entry of the id map is identical
+	 * is expensive.
+	 * See https://bugs.libcamera.org/show_bug.cgi?id=31 for further details
+	 */
+
+	switch (policy) {
+	case MergePolicy::KeepExisting:
+		controls_.merge(source.controls_);
+		break;
+	case MergePolicy::OverwriteExisting:
+		source.controls_.merge(controls_);
+		controls_.swap(source.controls_);
+		break;
+	}
+}
+
 /**
  * \brief Check if the list contains a control with the specified \a id
  * \param[in] id The control numerical ID