weak_ptr, shared_ptr, thread safety. Вопрос по блокировкам.
От: bratka  
Дата: 27.03.06 20:39
Оценка:
Сначала из документации:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);

// some time later

if(int * r = q.get())
{
// use *r
}

Imagine that after the if, but immediately before r is used, another thread executes the statement p.reset(). Now r is a dangling pointer.

The solution to this problem is to create a temporary shared_ptr from q:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock())
{
// use *r
}

Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will stay alive until r goes out of scope or is reset. By obtaining a shared_ptr to the object, we have effectively locked it against destruction.

---

Теперь собственно сам вопрос, возможно ли вместо копирования указателя, "стандартными средствами" boost заблокировать нить пытающуюся удалить объект на который существует слабая ссылка weak_ptr.

В чем собственно проблема:
Нельзя создавать shared_ptr из weak_ptr в потоке А, зная что в другом потоке (Б) объект (вернее его shared_ptr) может быть удален. Владельцем указателя является поток Б. Именно он определяет время, как указателя так соответственно и инстанса. "Нельзя" не потому что я доку неправильно прочитал, а такова постановка задачи.
То-есть если в потоке Б, было принято решение указатель удалить, то поток А должен получить фигу в виде weak_ptr::get() == NULL, если поток А в данный момент еще (или уже) использует указатель, то поток Б обязан ждать, хоть до морковкиного заговения, но указатель не удалять.
Использование
if(int * r = q.get())
{
// use *r
}
приведет к нарушению защиты памяти, и инвалидации указателя.
Использование
if(shared_ptr<int> r = q.lock())
{
// use *r
}
приведет к неблокируемому удалению указателя в потоке Б.

Я вижу 2 варианта:
1. Сделать блокирующий фасад над shared_ptr/weak_ptr.
2. искорёжить weak_ptr::get() и деструкотр shared_ptr.

1-й вариант конечно "правильный", 2-й вариант безобразный и must die.

Вопрос к многоуважаемому All, есть ли другие варианты ?

Учитывая, что shared_ptr уже thread safe, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.