Я пытаюсь понять, как я могу гарантировать, что счетчик ссылок на объекты является потокобезопасным.
class MyObject{
//Other implementation details
private:
mutable volatile LONGLONG * m_count;
IData * m_data;
};
Предположим, что необходимое объявление класса есть, просто сохраняя простоту. Вот реализация конструктора копирования и деструктора.
MyObject::MyObject(const MyObject& rhs) : m_count(rhs.m_count), m_data(rhs.m_data){
InterlockedIncrement64(m_count);
}
MyObject::~MyObject(){
if(InterlockedDecrement64(m_count) == 0)
delete m_data;
}
Эта ветка безопасна? Как виден список интилизации конструктора копирования, атомарный или нет? Это вообще имеет значение? Должен ли я устанавливать увеличенное значение счетчика в списке инициализации (возможно ли это)?
В нынешнем виде этого достаточно. Я думаю, что да, иначе как бы я мог попасть в сценарий, где thread1
копирует, а thread2
одновременно уничтожает, когда count == 1
. Между потоками должно быть рукопожатие, то есть поток 1 должен полностью скопировать объект до того, как объект потока 2 выйдет из области видимости, верно?
Прочитав некоторые из этих ответов, я вернулся и провел небольшое исследование. Boost реализует их shared_ptr очень похоже. Вот вызов деструктора.
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
Некоторые предположили, что в документации по boost четко указано, что присваивание не является потокобезопасным. Я согласен и не согласен. Я думаю, что в моем случае я не согласен. Мне нужно только рукопожатие между threadA и threadB. Я не думаю, что некоторые из проблем, описанных в некоторых ответах, применимы здесь (хотя они были откровенными ответами, которые я не полностью обдумал).
Пример ThreadA atach(SharedObject); //Общий объект передается по значению, увеличивается счетчик и т. д. и т. д.
ThreadB //Принимает объект, добавляет его в список общих объектов. ThreadB находится на таймере, который уведомляет все SharedObjects о событии. Перед уведомлением делается копия списка, защищенная критической секцией. CS выпускается, копии уведомляются.
ThreadA отсоединить (общий объект); //Удаляет общий объект из списка объектов
Теперь одновременно ThreadB посылает SharedOjbect и уже сделал копию списка до того, как ThreadA отсоединил указанный общий объект. Все в порядке нет?
std::atomic
, если вы просто хотите защитить счетчик, илиstd::mutex
, если вам нужна более широкая защита. - person Some programmer dude   schedule 14.09.2012