Копирование при записи с shared_ptr при многопоточности - PullRequest
3 голосов
/ 06 марта 2009

При отсутствии многопоточности, реализация copy-on-write для shared_ptr (от boost или tr1) с использованием unique() is простой. Какие изменения необходимо внести при многопоточности? Счетчик ссылок атомарный, поэтому я предполагаю, что я могу создать, скопировать-построить, читать и уничтожать экземпляры shared_ptr без дальнейшего беспокойства. Как насчет их обновления, в целом, и особенно при реализации копирование при записи? Нужны ли замки? Или используйте boost::atomic_store (почему это не задокументировано)? Или дождаться полностью атомной версии shared_ptr (не вариант)?

Edit:
sfossen, спасибо за ваш полезный ответ.
Таким образом, я прихожу к выводу, что если я изменяю наведенный объект только после отсоединения это через COW, так что только текущий поток владеет им, блокировка не требуется и реализация COW выглядит так же, как однопоточная при использовании shared_ptr с атомными реф-счетами.

Ответы [ 2 ]

6 голосов
/ 06 марта 2009

При использовании COW блокировка требуется только при копировании объектов, которые могут находиться в процессе изменения.

Таким образом, если COW объекта является объектом, установленным перед потоками и никогда не изменяется, блокировка не требуется.

Однако, если вы делаете копии копий, вам нужно хотя бы заблокировать во время начальной записи или убедиться, что копия имеет все изменения, прежде чем ее можно будет копировать снова.

Если вы не можете полностью гарантировать это, используйте блокировку или атомарные обновления.

Если вы хотите заблокировать:

Кажется, сейчас в стволе есть атомная версия.

Если вы не можете обновить boost, вы можете либо импортировать необходимые функции на данный момент, либо обернуть их в блокировку, например блокировку чтения / записи.

из shared_ptr.hpp

template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
{
    boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );

    sp.lock();
    p->swap( r );
    sp.unlock();

    return r; // return std::move( r )
}

статья о RWLocks

0 голосов
/ 08 марта 2009

Не безопасно копировать shared_ptr без какой-либо формы синхронизации, если только он не принадлежит потоку, выполняющему копирование. Гарантии безопасности потока применяются только к shared_ptr, принадлежащему потоку, где счетчик внутренних ссылок shared_ptr может быть разделен shared_ptr, принадлежащим другим потокам.

Вам нужно поведение, которое я бы назвал атомарно потокобезопасным, которого в настоящее время нет в shared_ptr и, вероятно, не будет даже после C ++ 0x. Имя shared_ptr, вероятно, немного сбивает с толку, поскольку вы не можете на самом деле делить shared_ptr между потоками без синхронизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...