What is the cost of calling member function via shared pointer?
Asked Answered
B

0

0

It is often stated that dereferencing a smart pointer does not have notable performance impacts. (For example here: C Smart Pointer Performance)

I am now wondering if this is really true. I understand that it could be, if operations on the object referenced are atomic.

Thinking of code based on this snippets:

class Worker
{
    [...]
    public:
        void setDataProvider( shared_ptr<DataProvider> p )
        {
            m_provider = p;
        }

        void doWork()
        {
            [...]
            for(;;) {
                int d = m_provider->getSomeData();

                [ do something with d ]
            }
        }

    private:

        shared_ptr<DataProvider>   m_provider;
};

doWork() will be permanently executed, and from time to time setDataProvider() is called from a second thread. Quite a normal smart pointer usage scenario.

Common consensus says that setDataProvider() has some extra costs, as the lock-protected refcount has to be changed, but m_provider->getSomeData() hasn't. It is said to be comparable to normal pointer dereferencing, at least no costly locking is needed.

But how can that work? Lets assume, getSomeData() is not an atomic operation, it might have some logic and a notable execution time.

How is *m_provider protected from being deleted while getSomeData() is executed? The class might be the only owner of the object. Overwriting m_provider will lower the pointer's refcount by one. Either m_provider->getSomeData() temporarily has to raise the refcount, or the object is being protected from deletion otherwise while getSomeData() runs.

In both cases some costly synchronization/locking mechanism is needed.

addendum: I used the standard shared_ptr in the example, as I am wondering about this in general. However the real code uses QSharedPointer so I am specially interested about this. I naively assumed both would have the same thread safety, which might be wrong.

Brazell answered 10/8, 2015 at 11:57 Comment(5)
In setDataProvider() the shared pointer assignments is not atomic. You still need to use a mutex to make sure you are not reading while writing or doing a double write. See this answer for more information: https://mcmap.net/q/518832/-atomic-reference-countingJog
Is this also true for QSharedPointer? Qt documentation just says "QSharedPointer and QWeakPointer are thread-safe and operate atomically on the pointer value."Brazell
[Formatting]: It is backquote ` which is to be used for inlined formatted code. star * is for italicFill
@Brazell Not being familiar with Qt I cannot give you a definite answer but doc does say accessing the pointer value is thread safe but it [...]provide no guarantee about the object being pointed to.Jog
@Nathan: Thanks! You're right. When I first read that sentence I thought it means just "smart pointers do not automatically make your object threadsafe". But indeed it also refers to this... Just looked into the Qt code and there is no safety applied. Using "->" on the pointer just passes the call to the object.Brazell

© 2022 - 2024 — McMap. All rights reserved.