Какова стоимость вызова функции-члена через общий указатель?

Часто утверждается, что разыменование умного указателя не оказывает заметного влияния на производительность. (Например, здесь: C Smart Pointer Performance)

Теперь мне интересно, правда ли это. Я понимаю, что это может быть, если операции над указанным объектом являются атомарными.

Думая о коде на основе этих фрагментов:

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() будет выполняться навсегда, и время от времени setDataProvider() вызывается из второго потока. Вполне нормальный сценарий использования умного указателя.

Общее мнение говорит, что setDataProvider() имеет некоторые дополнительные расходы, так как необходимо изменить счет, защищенный блокировкой, но m_provider->getSomeData() не имеет. Говорят, что он сравним с обычным разыменованием указателя, по крайней мере, дорогостоящей блокировки не требуется.

Но как это может работать? Предположим, getSomeData() это не атомарная операция, она может иметь некоторую логику и заметное время выполнения.

Как *m_provider защищен от удаления во время getSomeData() выполняется? Класс может быть единственным владельцем объекта. Перезапись m_provider снизит счетчик указателя на единицу. Или m_provider->getSomeData() временно должен повысить счет, или объект защищен от удаления, в то время как getSomeData() пробеги.

В обоих случаях требуется дорогостоящий механизм синхронизации / блокировки.

Приложение: я использовал стандарт shared_ptr в примере, как мне интересно об этом вообще. Однако реальный код использует QSharedPointer поэтому я особенно заинтересован в этом. Я наивно полагал, что оба будут иметь одинаковую безопасность потоков, что может быть неправильно.

0 ответов

Другие вопросы по тегам