[v2,1/3] libcamera: framebuffer_allocator: Move from argument in constructor
diff mbox series

Message ID 20240310143023.752559-2-pobrn@protonmail.com
State Accepted
Commit 443734023c1c953a3e4d0f3404b0d054f2449d99
Headers show
Series
  • couple FrameBufferAllocator changes
Related show

Commit Message

Barnabás Pőcze March 10, 2024, 2:30 p.m. UTC
The single argument, of type `std::shared_ptr<Camera>`,
is passed by value, so it can simply be moved from in order to
avoid calling the copy constructor.

Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
---
 src/libcamera/framebuffer_allocator.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Kieran Bingham March 11, 2024, 2:14 p.m. UTC | #1
Quoting Barnabás Pőcze (2024-03-10 14:30:33)
> The single argument, of type `std::shared_ptr<Camera>`,
> is passed by value, so it can simply be moved from in order to
> avoid calling the copy constructor.
> 


Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
> ---
>  src/libcamera/framebuffer_allocator.cpp | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
> index 94389735..8cf45ab2 100644
> --- a/src/libcamera/framebuffer_allocator.cpp
> +++ b/src/libcamera/framebuffer_allocator.cpp
> @@ -59,7 +59,7 @@ LOG_DEFINE_CATEGORY(Allocator)
>   * \param[in] camera The camera
>   */
>  FrameBufferAllocator::FrameBufferAllocator(std::shared_ptr<Camera> camera)
> -       : camera_(camera)
> +       : camera_(std::move(camera))
>  {
>  }
>  
> -- 
> 2.44.0
> 
>
Jacopo Mondi March 11, 2024, 5:01 p.m. UTC | #2
Hi Barnabás

On Sun, Mar 10, 2024 at 02:30:33PM +0000, Barnabás Pőcze wrote:
> The single argument, of type `std::shared_ptr<Camera>`,
> is passed by value, so it can simply be moved from in order to
> avoid calling the copy constructor.
>
> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
> ---
>  src/libcamera/framebuffer_allocator.cpp | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
> index 94389735..8cf45ab2 100644
> --- a/src/libcamera/framebuffer_allocator.cpp
> +++ b/src/libcamera/framebuffer_allocator.cpp
> @@ -59,7 +59,7 @@ LOG_DEFINE_CATEGORY(Allocator)
>   * \param[in] camera The camera
>   */
>  FrameBufferAllocator::FrameBufferAllocator(std::shared_ptr<Camera> camera)
> -	: camera_(camera)
> +	: camera_(std::move(camera))

However, if the caller of the FrameBufferAllocator constructor uses
move() when calling the constructur, this will not increase the
shared_ptr<> reference count and this could lead to a path where the
object held by the shared_ptr<> (the camera in this case) is released
before the FrameBufferAllocator instance referencing it ?

Do yuo think it's an issue ? Applications shouldn't

        FrameBufferAllocator(std::move(camera))

but is there anything preventing them from doing so ?

>  {
>  }
>
> --
> 2.44.0
>
>
Barnabás Pőcze March 11, 2024, 5:42 p.m. UTC | #3
Hi


2024. március 11., hétfő 18:01 keltezéssel, Jacopo Mondi <jacopo.mondi@ideasonboard.com> írta:

> Hi Barnabás
> 
> On Sun, Mar 10, 2024 at 02:30:33PM +0000, Barnabás Pőcze wrote:
> > The single argument, of type `std::shared_ptr<Camera>`,
> > is passed by value, so it can simply be moved from in order to
> > avoid calling the copy constructor.
> >
> > Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
> > ---
> >  src/libcamera/framebuffer_allocator.cpp | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
> > index 94389735..8cf45ab2 100644
> > --- a/src/libcamera/framebuffer_allocator.cpp
> > +++ b/src/libcamera/framebuffer_allocator.cpp
> > @@ -59,7 +59,7 @@ LOG_DEFINE_CATEGORY(Allocator)
> >   * \param[in] camera The camera
> >   */
> >  FrameBufferAllocator::FrameBufferAllocator(std::shared_ptr<Camera> camera)
> > -	: camera_(camera)
> > +	: camera_(std::move(camera))
> 
> However, if the caller of the FrameBufferAllocator constructor uses
> move() when calling the constructur, this will not increase the
> shared_ptr<> reference count and this could lead to a path where the
> object held by the shared_ptr<> (the camera in this case) is released
> before the FrameBufferAllocator instance referencing it ?

That is not possible. The constructor's argument holds a reference to the camera
object preventing it from being destroyed.


> 
> Do yuo think it's an issue ? Applications shouldn't
> 
>         FrameBufferAllocator(std::move(camera))
> 
> but is there anything preventing them from doing so ?

The observable behaviour for the caller does not really change after the proposed change.
If someone uses `FrameBufferAllocator(std::move(camera))`, then that will construct
a temporary with the shared_ptr's move constructor, so `camera` will point to nullptr
afterwards, regardless of what is done inside the constructor. This is what happens
now and what will happen after this change.

Previously if someone did

  FrameBufferAllocator { ... }

then there would be
  * two copy constructor invocations, or
  * one move constructor and one copy constructor invocation.
depending on the type of `...` above.

The first one when constructing the temporary for the argument,
and the second one when constructing the member variable from the argument.

With the proposed change, there will be at most one copy constructor call
when constructing a FrameBufferAllocator.


> 
> >  {
> >  }
> >
> > --
> > 2.44.0
> >
> >


Regards,
Barnabás Pőcze
Jacopo Mondi March 12, 2024, 8:46 a.m. UTC | #4
Hi Barnabás

On Mon, Mar 11, 2024 at 05:42:55PM +0000, Barnabás Pőcze wrote:
> Hi
>
>
> 2024. március 11., hétfő 18:01 keltezéssel, Jacopo Mondi <jacopo.mondi@ideasonboard.com> írta:
>
> > Hi Barnabás
> >
> > On Sun, Mar 10, 2024 at 02:30:33PM +0000, Barnabás Pőcze wrote:
> > > The single argument, of type `std::shared_ptr<Camera>`,
> > > is passed by value, so it can simply be moved from in order to
> > > avoid calling the copy constructor.
> > >
> > > Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
> > > ---
> > >  src/libcamera/framebuffer_allocator.cpp | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
> > > index 94389735..8cf45ab2 100644
> > > --- a/src/libcamera/framebuffer_allocator.cpp
> > > +++ b/src/libcamera/framebuffer_allocator.cpp
> > > @@ -59,7 +59,7 @@ LOG_DEFINE_CATEGORY(Allocator)
> > >   * \param[in] camera The camera
> > >   */
> > >  FrameBufferAllocator::FrameBufferAllocator(std::shared_ptr<Camera> camera)
> > > -	: camera_(camera)
> > > +	: camera_(std::move(camera))
> >
> > However, if the caller of the FrameBufferAllocator constructor uses
> > move() when calling the constructur, this will not increase the
> > shared_ptr<> reference count and this could lead to a path where the
> > object held by the shared_ptr<> (the camera in this case) is released
> > before the FrameBufferAllocator instance referencing it ?
>
> That is not possible. The constructor's argument holds a reference to the camera
> object preventing it from being destroyed.
>
>
> >
> > Do yuo think it's an issue ? Applications shouldn't
> >
> >         FrameBufferAllocator(std::move(camera))
> >
> > but is there anything preventing them from doing so ?
>
> The observable behaviour for the caller does not really change after the proposed change.
> If someone uses `FrameBufferAllocator(std::move(camera))`, then that will construct
> a temporary with the shared_ptr's move constructor, so `camera` will point to nullptr
> afterwards, regardless of what is done inside the constructor. This is what happens
> now and what will happen after this change.

I think the key point is also that std::move() of a shared_ptr<>
effectively resets it, so it's not something anyone would do, which
makes my argument moot

>
> Previously if someone did
>
>   FrameBufferAllocator { ... }
>
> then there would be
>   * two copy constructor invocations, or
>   * one move constructor and one copy constructor invocation.
> depending on the type of `...` above.
>
> The first one when constructing the temporary for the argument,
> and the second one when constructing the member variable from the argument.
>
> With the proposed change, there will be at most one copy constructor call
> when constructing a FrameBufferAllocator.
>

For reference, this is the code generated by goldbot for the two use
cases with the following code snippet:

-------------------------------------------------------------------------------
#include <memory>

using namespace std;

class klass
{
public:
    klass(shared_ptr<int> i)
        : i_(i)
        // : i_(move(i))
    {
    }

private:
    shared_ptr<int> i_;
};

int main()
{
    shared_ptr<int> i = std::make_shared<int>(5);

    klass k(i);

    return 0;
}
-------------------------------------------------------------------------------


* move)
	mov     rbx, QWORD PTR [rbp-24]
        mov     rax, QWORD PTR [rbp-32]
        mov     rdi, rax
        call    std::remove_reference<std::shared_ptr<int>&>::type&& std::move<std::shared_ptr<int>&>(std::shared_ptr<int>&)
        mov     rsi, rax
        mov     rdi, rbx
        call    std::shared_ptr<int>::shared_ptr(std::shared_ptr<int>&&) [complete object constructor]


* non move)
        mov     rax, QWORD PTR [rbp-8]
        mov     rdx, QWORD PTR [rbp-16]
        mov     rsi, rdx
        mov     rdi, rax
        call    std::shared_ptr<int>::shared_ptr(std::shared_ptr<int> const&) [complete object constructor]

I hoped for the compiler to be smart enough to avoid calling the copy
constructor for both the temporary object and the class member
initialization, but that doesn't seem the case, so

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

Thanks
  j

>
> >
> > >  {
> > >  }
> > >
> > > --
> > > 2.44.0
> > >
> > >
>
>
> Regards,
> Barnabás Pőcze

Patch
diff mbox series

diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
index 94389735..8cf45ab2 100644
--- a/src/libcamera/framebuffer_allocator.cpp
+++ b/src/libcamera/framebuffer_allocator.cpp
@@ -59,7 +59,7 @@  LOG_DEFINE_CATEGORY(Allocator)
  * \param[in] camera The camera
  */
 FrameBufferAllocator::FrameBufferAllocator(std::shared_ptr<Camera> camera)
-	: camera_(camera)
+	: camera_(std::move(camera))
 {
 }