[libcamera-devel] [PATCH v4 6/6] libcamera: request: Make it extensible

Kieran Bingham kieran.bingham at ideasonboard.com
Thu Apr 22 12:22:24 CEST 2021


Hi Laurent,

On 20/04/2021 23:18, Laurent Pinchart wrote:
> Hi Kieran,
> 
> Thank you for the patch.
> 
> On Tue, Apr 20, 2021 at 02:07:41PM +0100, Kieran Bingham wrote:
>> Provide an extensible private object for the Request class.
>> This allows us to make modifications to the private API and storage of
>> requests without affecting the public API or ABI.
>>
>> The D pointer is obtained in all Request functions implemented in the
>> request.cpp file along with an assertion that the D pointer was valid to
>> provide extra validation checking that the Request has not been
>> deleted, while in use as it is 'owned' by the application.
> 
> s/, while in use/ while in use,/
> 
>>
>> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>>
>> ---
>> The assertions added in findBuffer, complete() and completeBuffer()
>> allow us to ensure that the Request is still valid while asynchronous
>> actions occur on the Request internally in libcamera, and provide
>> (almost) equivalent functionality as the Request Canary previously
>> proposed.
> 
> Does std::unique_ptr<> guarantees that it will reset its internal
> pointer when deleted ? libc++ calls reset() in the destructor, and
> stdlibc++ seems to set the pointer to nullptr manually, but that doesn't
> seem to be guaranteed by the C++ standard.

I've manually tested that it gets reset, but that doesn't offer any
guarantee beyond that.




>> The additions in reuse() and addBuffer() are called from applications,
>> so the assertions may be less helpful there, but I've added them for
>> consistency.
>>
>>  include/libcamera/request.h |  4 +++-
>>  src/libcamera/request.cpp   | 34 ++++++++++++++++++++++++++++++++--
>>  2 files changed, 35 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/libcamera/request.h b/include/libcamera/request.h
>> index 4cf5ff3f7d3b..909a1aebc2d2 100644
>> --- a/include/libcamera/request.h
>> +++ b/include/libcamera/request.h
>> @@ -24,8 +24,10 @@ class CameraControlValidator;
>>  class FrameBuffer;
>>  class Stream;
>>  
>> -class Request
>> +class Request : public Extensible
>>  {
>> +	LIBCAMERA_DECLARE_PRIVATE(Request)
>> +
>>  public:
>>  	enum Status {
>>  		RequestPending,
>> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
>> index ce2dd7b17f10..977bfac4fce6 100644
>> --- a/src/libcamera/request.cpp
>> +++ b/src/libcamera/request.cpp
>> @@ -28,6 +28,19 @@ namespace libcamera {
>>  
>>  LOG_DEFINE_CATEGORY(Request)
>>  
>> +class Request::Private : public Extensible::Private
>> +{
>> +	LIBCAMERA_DECLARE_PUBLIC(Request)
>> +
>> +public:
>> +	Private(Request *request);
>> +};
>> +
>> +Request::Private::Private(Request *request)
>> +	: Extensible::Private(request)
>> +{
>> +}
>> +
>>  /**
>>   * \enum Request::Status
>>   * Request completion status
>> @@ -73,8 +86,8 @@ LOG_DEFINE_CATEGORY(Request)
>>   *
>>   */
>>  Request::Request(Camera *camera, uint64_t cookie)
>> -	: camera_(camera), sequence_(0), cookie_(cookie),
>> -	  status_(RequestPending), cancelled_(false)
>> +	: Extensible(new Private(this)), camera_(camera), sequence_(0),
>> +	  cookie_(cookie), status_(RequestPending), cancelled_(false)
> 
> Should we move some of the data to Private (in a subsequent patch) ? As
> an exercise, how about moving the member data that we think will be
> subject to change when we'll rework the request completion API, and see
> if we manage to complete that rework without breaking the API of the
> request class ?

Of course, the goal of this patch isn't just to add assertions, it's to
make it extensible so we can extend it in subsequent patches ;-)


> A subsequent patch should also move the public functions that are not
> called by applications to the Private class.

Agreed, I wanted to keep this patch as simple as possible to start with.

> 
>>  {
>>  	/**
>>  	 * \todo Should the Camera expose a validator instance, to avoid
>> @@ -114,6 +127,9 @@ Request::~Request()
>>   */
>>  void Request::reuse(ReuseFlag flags)
>>  {
>> +	Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>> +
>>  	LIBCAMERA_TRACEPOINT(request_reuse, this);
>>  
>>  	pending_.clear();
>> @@ -179,6 +195,9 @@ void Request::reuse(ReuseFlag flags)
>>   */
>>  int Request::addBuffer(const Stream *stream, FrameBuffer *buffer)
>>  {
>> +	Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>> +
>>  	if (!stream) {
>>  		LOG(Request, Error) << "Invalid stream reference";
>>  		return -EINVAL;
>> @@ -214,6 +233,9 @@ int Request::addBuffer(const Stream *stream, FrameBuffer *buffer)
>>   */
>>  FrameBuffer *Request::findBuffer(const Stream *stream) const
>>  {
>> +	const Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>> +
>>  	const auto it = bufferMap_.find(stream);
>>  	if (it == bufferMap_.end())
>>  		return nullptr;
>> @@ -282,6 +304,8 @@ FrameBuffer *Request::findBuffer(const Stream *stream) const
>>   */
>>  void Request::complete()
>>  {
>> +	Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>>  	ASSERT(status_ == RequestPending);
>>  	ASSERT(!hasPendingBuffers());
>>  
>> @@ -307,6 +331,9 @@ void Request::complete()
>>   */
>>  bool Request::completeBuffer(FrameBuffer *buffer)
>>  {
>> +	Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>> +
>>  	LIBCAMERA_TRACEPOINT(request_complete_buffer, this, buffer);
>>  
>>  	int ret = pending_.erase(buffer);
>> @@ -330,6 +357,9 @@ bool Request::completeBuffer(FrameBuffer *buffer)
>>   */
>>  std::string Request::toString() const
>>  {
>> +	const Private *const d = LIBCAMERA_D_PTR();
>> +	ASSERT(d);
>> +
>>  	std::stringstream ss;
>>  
>>  	/* Pending, Completed, Cancelled(X). */
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list