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, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
Re: weak_ptr, shared_ptr, thread safety. Вопрос по блокировк
Re: weak_ptr, shared_ptr, thread safety. Вопрос по блокировк
От:
Аноним
Дата:
28.03.06 07:38
Оценка:
... B>Использование B>if(shared_ptr<int> r = q.lock()) B>{ B> // use *r B>} B>приведет к неблокируемому удалению указателя в потоке Б.
Это интересно почему? Фактически когда q.lock() вернет указатель на еще живой объект, кол-во ссылок ++.
Re: weak_ptr, shared_ptr, thread safety. Вопрос по блокировк
От:
Аноним
Дата:
28.03.06 08:01
Оценка:
B>Я вижу 2 варианта: B>1. Сделать блокирующий фасад над shared_ptr/weak_ptr. B>2. искорёжить weak_ptr::get() и деструкотр shared_ptr.
B>1-й вариант конечно "правильный", 2-й вариант безобразный и must die.
B>Вопрос к многоуважаемому All, есть ли другие варианты ?
B>Учитывая, что shared_ptr уже thread safe, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
А почему дополнительный mutex сильно скажется на производительности? У тебя что, приложение только и занимается тем, что достаёт указатель из именно этого weak_ptr (не обязательно ведь "улучшать" все weak_ptr, только тот, где это надо)? Может это можно делать пореже?
Ну, видимо, не подходят тебе shared_/weak_ptr.
Так ты храни указатель не на сам объект, а на того кто может его отдать (либо не отдать), а он уж пусть разбирается.
Re[2]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
Здравствуйте, Аноним, Вы писали:
А>... B>>Использование B>>if(shared_ptr<int> r = q.lock()) B>>{ B>> // use *r B>>} B>>приведет к неблокируемому удалению указателя в потоке Б.
А>Это интересно почему? Фактически когда q.lock() вернет указатель на еще живой объект, кол-во ссылок ++.
Теперь удаляем shared_ptr в потоке Б (кол-во ссылок --), объект остается только в потоке А. Поменяли владельца. Именно этого делать нельзя.
Re[2]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
Здравствуйте, Аноним, Вы писали:
B>>Я вижу 2 варианта: B>>1. Сделать блокирующий фасад над shared_ptr/weak_ptr. B>>2. искорёжить weak_ptr::get() и деструкотр shared_ptr.
B>>1-й вариант конечно "правильный", 2-й вариант безобразный и must die.
B>>Вопрос к многоуважаемому All, есть ли другие варианты ?
B>>Учитывая, что shared_ptr уже thread safe, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
А>А почему дополнительный mutex сильно скажется на производительности? У тебя что, приложение только и занимается тем, что достаёт указатель из именно этого weak_ptr (не обязательно ведь "улучшать" все weak_ptr, только тот, где это надо)? Может это можно делать пореже?
В данном потоке именно это и происходит: в бесконечном цикле, до тех пор пока возможно получить указатель на объект, получать его и проводить некую маленькую работу.
А>Ну, видимо, не подходят тебе shared_/weak_ptr.
weak_ptr/shared_ptr как раз очень подходят, жаль что нет механизма блокирования, и сохранения владельца. То-есть операции swap/reset — порочны в данной ситуации. А>Так ты храни указатель не на сам объект, а на того кто может его отдать (либо не отдать), а он уж пусть разбирается.
shared_ptr<shared_ptr<T>> ??
Re[3]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
От:
Аноним
Дата:
28.03.06 16:01
Оценка:
B>>>Я вижу 2 варианта: B>>>1. Сделать блокирующий фасад над shared_ptr/weak_ptr. B>>>2. искорёжить weak_ptr::get() и деструкотр shared_ptr.
B>>>1-й вариант конечно "правильный", 2-й вариант безобразный и must die.
B>>>Вопрос к многоуважаемому All, есть ли другие варианты ?
B>>>Учитывая, что shared_ptr уже thread safe, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
А>>А почему дополнительный mutex сильно скажется на производительности? У тебя что, приложение только и занимается тем, что достаёт указатель из именно этого weak_ptr (не обязательно ведь "улучшать" все weak_ptr, только тот, где это надо)? Может это можно делать пореже? B>В данном потоке именно это и происходит: в бесконечном цикле, до тех пор пока возможно получить указатель на объект, получать его и проводить некую маленькую работу.
Ну, указатель можно получать один раз а маленькую работу проводить 10 раз (это если он делает это непрерывно). Или забрать себе указатель и не отдавать до тех пор пока не поднимут какой-нибудь флажок.
А если он спит на event'е перед получением указателя то +1 mutex это уже не так много.
А>>Ну, видимо, не подходят тебе shared_/weak_ptr. B>weak_ptr/shared_ptr как раз очень подходят, жаль что нет механизма блокирования, и сохранения владельца. То-есть операции swap/reset — порочны в данной ситуации. А>>Так ты храни указатель не на сам объект, а на того кто может его отдать (либо не отдать), а он уж пусть разбирается. B>shared_ptr<shared_ptr<T>> ??
Нет. Просто сделать корректную обёртку над shared_ptr на все случаи жизни — довольно сложно. А тебе ведь надо 2 операции —
1) получить объект если он есть (+возможно, вернуть)
2) убить объект дождавшись момента, когда им никто не пользуется
У этих двух потоков наверняка есть какие-то общие данные, вот и добавь к ним эти два метода и реализуй их так, как ты хочешь — их ведь всего 2-3.
Re[4]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
Здравствуйте, Аноним, Вы писали:
B>>>>Я вижу 2 варианта: B>>>>1. Сделать блокирующий фасад над shared_ptr/weak_ptr. B>>>>2. искорёжить weak_ptr::get() и деструкотр shared_ptr.
B>>>>1-й вариант конечно "правильный", 2-й вариант безобразный и must die.
B>>>>Вопрос к многоуважаемому All, есть ли другие варианты ?
B>>>>Учитывая, что shared_ptr уже thread safe, наворачивать фассад с дополнительным мъютексом видится мне как удвоение времени операции доступа к данным. Что в конечном итоге скажется (и очень) на общей производительности системы.
А>>>А почему дополнительный mutex сильно скажется на производительности? У тебя что, приложение только и занимается тем, что достаёт указатель из именно этого weak_ptr (не обязательно ведь "улучшать" все weak_ptr, только тот, где это надо)? Может это можно делать пореже? B>>В данном потоке именно это и происходит: в бесконечном цикле, до тех пор пока возможно получить указатель на объект, получать его и проводить некую маленькую работу.
А>Ну, указатель можно получать один раз а маленькую работу проводить 10 раз (это если он делает это непрерывно). Или забрать себе указатель и не отдавать до тех пор пока не поднимут какой-нибудь флажок. А>А если он спит на event'е перед получением указателя то +1 mutex это уже не так много.
А>>>Ну, видимо, не подходят тебе shared_/weak_ptr. B>>weak_ptr/shared_ptr как раз очень подходят, жаль что нет механизма блокирования, и сохранения владельца. То-есть операции swap/reset — порочны в данной ситуации. А>>>Так ты храни указатель не на сам объект, а на того кто может его отдать (либо не отдать), а он уж пусть разбирается. B>>shared_ptr<shared_ptr<T>> ??
А>Нет. Просто сделать корректную обёртку над shared_ptr на все случаи жизни — довольно сложно. А тебе ведь надо 2 операции - А>1) получить объект если он есть (+возможно, вернуть) ---- А>2) убить объект дождавшись момента, когда им никто не пользуется
----
А>У этих двух потоков наверняка есть какие-то общие данные, вот и добавь к ним эти два метода и реализуй их так, как ты хочешь — их ведь всего 2-3.
//thread А
while(1)
{
if(mytype* ptr__=weak_ptr_obj.get())
{
sem_wait(ptr__->semaphore);
// can do the things with ptr__;
}
}
//thread B
// nash_shared_ptr attribute of someclass
~someclass(){
while(nash_shared_ptr.use_count()); //псевдо-решение. беда ... даже биде можно сказать. неблокируемый цикл, а в это время в потоке А объект используется и висит на семафоре — типичный програмный дедлок.
}
тупейшее решение выглядит так:
//thread А
while(1)
{
if(mytype* ptr__=weak_ptr_obj.get())
{
if(pthread_mutex_trylock(ptr__->ptrlock)) // неважно занят или мертв errno не проверяем
break;
sem_wait(ptr__->semaphore);
// can do the things with ptr__;
pthread_mutex_unlock(ptr__->ptrlock);
}
}
//thread B:
~someclass(){
mytype* tmptpr=nash_shared_ptr.get();
sem_post(nash_shared_ptr.get()->semaphore); // очень скользко — смотрим ниже
sem_post(nash_shared_ptr.get()->semaphore); // для надежности
pthread_mutex_lock(tmpptr->ptr_lock); // очень надеемся, что мы заблокировали мьютекс сами, а не попали в очередной дедлок ...
pthread_mutex_destroy(tmpptr->ptr_lock);
}
// умираем , и nash_shared_ptr оходит в мир иной вместе с прощальной песней деструктора
То-есть картина удручающая.
грубая и тупая сила. никакой элегантности.
И никто не может гарантировать, что в последствии будет везде работать на ура. То-есть если одна итерация цикла в потоке А займет меньше 10мс то есть очень высокий шанс, что деструктор someclass в потоке Б так и останется висеть до ишачей пасхи.
Похоже у меня проблема где-то на генетическом уровне
Re[5]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
B>//thread B: B>~someclass(){ B> mytype* tmptpr=nash_shared_ptr.get(); B> sem_post(nash_shared_ptr.get()->semaphore); // очень скользко — смотрим ниже B> sem_post(nash_shared_ptr.get()->semaphore); // для надежности B> pthread_mutex_lock(tmpptr->ptr_lock); // очень надеемся, что мы заблокировали мьютекс сами, а не попали в очередной дедлок ...
// ошибку допустил, исправляю:
pthread_mutex_lock(tmpptr->ptr_lock); // unlock before destroy. B> pthread_mutex_destroy(tmpptr->ptr_lock); B>} B>// умираем , и nash_shared_ptr оходит в мир иной вместе с прощальной песней деструктора
B>Похоже у меня проблема где-то на генетическом уровне
суть проблемы правда от этого не изменилась.
Re[6]: weak_ptr, shared_ptr, thread safety. Вопрос по блокир
B>>//thread B: B>>~someclass(){ B>> mytype* tmptpr=nash_shared_ptr.get(); B>> sem_post(nash_shared_ptr.get()->semaphore); // очень скользко — смотрим ниже B>> sem_post(nash_shared_ptr.get()->semaphore); // для надежности B>> pthread_mutex_lock(tmpptr->ptr_lock); // очень надеемся, что мы заблокировали мьютекс сами, а не попали в очередной дедлок ... B>// ошибку допустил, исправляю:
/// B>pthread_mutex_lock(tmpptr->ptr_lock); // unlock before destroy. --- copy-paste not works without correction
pthread_mutex_unlock(tmpptr->ptr_lock); // !!!!!!!!!!!!! DNA error of the coder. B>> pthread_mutex_destroy(tmpptr->ptr_lock); B>>} B>>// умираем , и nash_shared_ptr оходит в мир иной вместе с прощальной песней деструктора
B>>Похоже у меня проблема где-то на генетическом уровне B>суть проблемы правда от этого не изменилась.