Копировать при записи с shared_ptr

Итак, у меня есть простой cow_ptr, Это выглядит примерно так:

template<class T, class Base=std::shared_ptr<T const>>
struct cow_ptr:private Base{
using Base::operator*;
using Base::operator->;
using Base::operator bool;
// etc

cow_ptr(std::shared_ptr<T> ptr):Base(ptr){}

// defaulted special member functions

template<class F>
decltype(auto) write(F&& f){
if (!unique()) self_clone();
Assert(unique());
return std::forward<F>(f)(const_cast<T&>(**this));
}
private:
void self_clone(){
if (!*this) return;
*this = std::make_shared<T>(**this);
Assert(unique());
}
};

это гарантирует, что он имеет неконстантный T и гарантирует, что это unique когда это .write([&](T&){})с этим.

обесценивание .unique() кажется, указывает на то, что этот дизайн имеет недостатки.

Я предполагаю, что если мы начнем с cow_ptr<int> ptr с 1 в потоке A, передать его в поток B, сделать его уникальным, изменить его на 2, проходить ptr это назад и читать это в потоке A мы создали условия гонки.

Как это исправить? Могу ли я просто добавить барьер памяти в write? Который из? Или проблема более фундаментальная?

Менее вероятны симптомы на x86 из-за того, что согласованность памяти x86 выходит за рамки требований C ++?

7

Решение

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

if(sp.unique()) {
// some deinitialisation
} else {
// somebody else will deinitialise.
}

Вполне возможно, что он не сможет деинициализироваться, если он будет выполняться 2 раза одновременно.

В вашем конкретном случае я не вижу проблем, потому что

  1. если он не был уникальным и стал уникальным — это не страшно, просто сделайте дополнительную копию
  2. если он был уникальным и стал не уникальным, то вы меняете и копируете один и тот же экземпляр в двух разных потоках (что в любом случае будет проблемой)

Я не думаю, что есть какие-либо другие проблемы с заказами на доступ к памяти, так как счетчики в shared_ptr являются атомными.

Я бы, наверное, просто переключился на use_count == 1может быть с соответствующим комментарием

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]