[libcamera-devel] [PATCH 5/6] libcamera: controls: Rationalize idMap() function

Kieran Bingham kieran.bingham at ideasonboard.com
Thu Sep 2 17:00:13 CEST 2021


On 01/09/2021 15:37, Jacopo Mondi wrote:
> The ControlList class has a pair of accessor functions with a similar
> signature:
> 
> 	const ControlInfoMap *infoMap() const { return infoMap_; }
> 	const ControlIdMap *idMap() const { return idmap_; }
> 
> As ControlList::infoMap_ can be nullptr, the two functions returns the
> class members as pointers and not references.
> 
> The ControlInfoMap class has instead:
> 
> 	const ControlIdMap &idmap() const { return *idmap_; }
> 
> Which is disturbingly different in the signature and return type.
> 
> Rationalize the accessor function names by stabilizing on:
> 
> 	const ControlIdMap *idMap() const { return idmap_; }
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  include/libcamera/controls.h         | 2 +-
>  src/libcamera/camera_sensor.cpp      | 2 +-
>  src/libcamera/control_serializer.cpp | 4 ++--
>  src/libcamera/controls.cpp           | 4 ++--
>  src/libcamera/delayed_controls.cpp   | 4 ++--
>  5 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
> index 8e5bc8b70b94..de6faf600e19 100644
> --- a/include/libcamera/controls.h
> +++ b/include/libcamera/controls.h
> @@ -338,7 +338,7 @@ public:
>  	iterator find(unsigned int key);
>  	const_iterator find(unsigned int key) const;
>  
> -	const ControlIdMap &idmap() const { return *idmap_; }
> +	const ControlIdMap *idMap() const { return idmap_; }
>  
>  private:
>  	bool validate();
> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> index 876685097f76..48af3a617ee1 100644
> --- a/src/libcamera/camera_sensor.cpp
> +++ b/src/libcamera/camera_sensor.cpp
> @@ -176,7 +176,7 @@ int CameraSensor::validateSensorDriver()
>  		V4L2_CID_CAMERA_SENSOR_ROTATION,
>  	};
>  
> -	const ControlIdMap &controls = subdev_->controls().idmap();
> +	const ControlIdMap &controls = *subdev_->controls().idMap();

Aye? Is this legal?

Is that declaring a reference against a dereferenced pointer?

I can't tell if that's making a copy - or ... time for a compile-explorer:

	https://godbolt.org/z/j75669Mrf

Ok - so it's not making a copy, and it generates identical code to:

	const ControlIdMap *controls = subdev_->controls().idMap()

But without you having to change all the uses of controls to controls->
instead of controls. ?

But given there are only 3 ... ?


https://isocpp.org/wiki/faq/references#refs-vs-ptrs
 states
>  "Use references when you can, and pointers when you have to."

But https://isocpp.org/wiki/faq/references#refs-not-null
makes it clear:

> It means this is illegal:
> 
>     T* p = nullptr;
>     T& r = *p;  // illegal

So we have to be /really/ sure that idMap() would not return a nullptr,
or we get into undefined behaviour, and the cpu turns into a black hole.

I suspect a reference use here is dangerous ...





>  	for (uint32_t ctrl : optionalControls) {
>  		if (!controls.count(ctrl))
>  			LOG(CameraSensor, Debug)
> diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp
> index d4377c024079..7eef041a16ee 100644
> --- a/src/libcamera/control_serializer.cpp
> +++ b/src/libcamera/control_serializer.cpp
> @@ -190,7 +190,7 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
>  	for (const auto &ctrl : infoMap)
>  		valuesSize += binarySize(ctrl.second);
>  
> -	const ControlIdMap *idmap = &infoMap.idmap();
> +	const ControlIdMap *idmap = infoMap.idMap();
>  	enum ipa_controls_id_map_type idMapType;
>  	if (idmap == &controls::controls)
>  		idMapType = IPA_CONTROL_ID_MAP_CONTROLS;
> @@ -530,7 +530,7 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
>  		}
>  
>  		const ControlInfoMap *infoMap = iter->first;
> -		idMap = &infoMap->idmap();
> +		idMap = infoMap->idMap();
>  	} else {
>  		switch (hdr->id_map_type) {
>  		case IPA_CONTROL_ID_MAP_CONTROLS:
> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
> index 96625edb1380..9b9bad212db3 100644
> --- a/src/libcamera/controls.cpp
> +++ b/src/libcamera/controls.cpp
> @@ -778,7 +778,7 @@ ControlInfoMap::const_iterator ControlInfoMap::find(unsigned int id) const
>  }
>  
>  /**
> - * \fn const ControlIdMap &ControlInfoMap::idmap() const
> + * \fn const ControlIdMap *ControlInfoMap::idMap() const
>   * \brief Retrieve the ControlId map
>   *
>   * Constructing ControlList instances for V4L2 controls requires a ControlIdMap
> @@ -832,7 +832,7 @@ ControlList::ControlList(const ControlIdMap &idmap, ControlValidator *validator)
>   * \param[in] validator The validator (may be null)
>   */
>  ControlList::ControlList(const ControlInfoMap &infoMap, ControlValidator *validator)
> -	: validator_(validator), idmap_(&infoMap.idmap()), infoMap_(&infoMap)
> +	: validator_(validator), idmap_(infoMap.idMap()), infoMap_(&infoMap)
>  {
>  }
>  
> diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp
> index 90ce7e0b5b52..763021ef09bb 100644
> --- a/src/libcamera/delayed_controls.cpp
> +++ b/src/libcamera/delayed_controls.cpp
> @@ -130,7 +130,7 @@ void DelayedControls::reset()
>  	/* Seed the control queue with the controls reported by the device. */
>  	values_.clear();
>  	for (const auto &ctrl : controls) {
> -		const ControlId *id = device_->controls().idmap().at(ctrl.first);
> +		const ControlId *id = device_->controls().idMap()->at(ctrl.first);
>  		/*
>  		 * Do not mark this control value as updated, it does not need
>  		 * to be written to to device on startup.
> @@ -158,7 +158,7 @@ bool DelayedControls::push(const ControlList &controls)
>  	}
>  
>  	/* Update with new controls. */
> -	const ControlIdMap &idmap = device_->controls().idmap();
> +	const ControlIdMap &idmap = *device_->controls().idMap();

Another location of taking a reference from a pointer.
I think this is likely to flag up the UBSAN, even if it compiles cleanly.


>  	for (const auto &control : controls) {
>  		const auto &it = idmap.find(control.first);
>  		if (it == idmap.end()) {
> 


More information about the libcamera-devel mailing list