Я пытаюсь понять, как работает COW, я нашел следующий класс на вики-книгах, но я не понимаю этот код.
template <class T>
class CowPtr
{
public:
typedef boost::shared_ptr<T> RefPtr;
private:
RefPtr m_sp;
void detach()
{
T* tmp = m_sp.get();
if( !( tmp == 0 || m_sp.unique() ) ) {
m_sp = RefPtr( new T( *tmp ) );
}
}
public:
CowPtr(T* t)
: m_sp(t)
{}
CowPtr(const RefPtr& refptr)
: m_sp(refptr)
{}
CowPtr(const CowPtr& cowptr)
: m_sp(cowptr.m_sp)
{}
CowPtr& operator=(const CowPtr& rhs)
{
m_sp = rhs.m_sp; // no need to check for self-assignment with boost::shared_ptr
return *this;
}
const T& operator*() const
{
return *m_sp;
}
T& operator*()
{
detach();
return *m_sp;
}
const T* operator->() const
{
return m_sp.operator->();
}
T* operator->()
{
detach();
return m_sp.operator->();
}
};
И я бы использовал его в своем многопоточном приложении на объекте карты, который является общим.
map<unsigned int, LPOBJECT> map;
Итак, я назначил его шаблону и теперь у меня есть:
CowPtr<map<unsigned int, LPOBJECT>> map;
А теперь мои вопросы:
Как я должен правильно взять экземпляр карты для случайного потока, который хочет только читать объекты карты?
Как я должен изменить объект карты из случайного потока, например. вставить новый объект или стереть его?
Код, который вы публикуете, плохой до такой степени, что его невозможно использовать;
Автор, кажется, не понимает, как const
работает в C ++.
Практически говоря: CoW требует некоторых знаний о
операции, выполняемые в классе. Оболочка CoW должна
вызвать копию, когда операция над обернутым объектом может
изменять; в случаях, когда обернутый объект может «вытекать» из указателей
или итераторы, которые позволяют модификацию, он также должен быть в состоянии
запомнить это, требовать глубокого копирования, как только что-нибудь
утечка. Код, который вы разместили, запускает копию в зависимости от
является ли указатель постоянным или нет, что совсем не то же самое
вещь. Таким образом, с std::map
звонит std::map<>::find
на
карта должна не инициировать копирование при записи, даже если указатель
не конст, а звонящий std::map<>::insert
должен, даже если
указатель постоянный
Что касается потоков: очень сложно сделать CoW
класс потокобезопасен без захвата блокировки для каждой операции
который может мутировать, потому что очень трудно знать, когда
фактические объекты распределяются между потоками. И это даже
сложнее, если объект позволяет указателям или итераторам
утечка, как и стандартные объекты библиотеки.
Вы не объясняете, почему вы хотите поточно-ориентированную карту CoW. какой
точка на карте, если каждый раз, когда вы добавляете или удаляете элемент,
вы получите новую копию, которая не видна в других
случаи? Если это просто, чтобы начать отдельные экземпляры с
копия существующей карты, std::map
имеет конструктор копирования
которая отлично справляется со своей работой, и вам не нужны какие-либо фантазии
обертка.
Как это работает?
Класс class CowPtr
содержит общий указатель на базовый объект. У него есть приватный метод для копирования конструкции нового объекта и назначения указателя на локальный общий указатель (если какой-либо другой объект содержит ссылку на него): void detach()
,
Соответствующей частью этого кода является то, что он имеет каждый метод как
const return_type&
method_name() const
и один раз без конст. Константа после метода гарантирует, что метод не изменяет объект, метод называется константный метод. Поскольку ссылка на базовый объект также является константой, этот метод вызывается каждый раз, когда вам требуется ссылка без ее изменения.
Однако, если вы решили изменить объект за ссылкой, например:
CowPtr<std::map<unsigned int, LPOBJECT>> map;
map->clear();
неконстантный метод T& operator->()
вызывается, который вызывает detach()
, При этом создается копия, если какая-либо другая CowPtr
или же shared_ptr
ссылается на тот же базовый объект (экземпляр <unsigned int, LPOBJECT>
в этом случае)
Как это использовать?
Как бы вы использовали std::shared_ptr
или же boost::shared_ptr
, Крутая вещь в этой реализации в том, что она делает все автоматически.
замечания
Это не COW, хотя, поскольку копия сделана, даже если вы не пишете, это скорее Копируй, если не гарантируешь, что не пишешь-Реализация.