Вопрос о контейнере Boost shared_ptr
-
02-07-2019 - |
Вопрос
Допустим, у меня есть контейнер (std::vector) указателей, используемых многопоточным приложением.При добавлении новых указателей в контейнер код защищается с помощью критической секции (boost::mutex).Все хорошо.Код должен быть способен возвращать один из этих указателей потоку для обработки, но другой отдельный поток может выбрать удаление одного из этих указателей, который, возможно, все еще используется.например ,:
thread1()
{
foo* p = get_pointer();
...
p->do_something();
}
thread2()
{
foo* p = get_pointer();
...
delete p;
}
Таким образом, thread2 может удалить указатель, пока thread1 его использует.Противный.
Поэтому вместо этого я хочу использовать контейнер Boost shared ptr.IIRC эти указатели будут подсчитываться по ссылкам, поэтому, пока я возвращаю общие ptr вместо необработанных указателей, удаление одного из контейнеров ФАКТИЧЕСКИ НЕ освободит его, пока последнее его использование не выйдет за пределы области видимости.т. е.
std::vector<boost::shared_ptr<foo> > my_vec;
thread1()
{
boost::shared_ptr<foo> sp = get_ptr[0];
...
sp->do_something();
}
thread2()
{
boost::shared_ptr<foo> sp = get_ptr[0];
...
my_vec.erase(my_vec.begin());
}
boost::shared_ptr<foo> get_ptr(int index)
{
lock_my_vec();
return my_vec[index];
}
В приведенном выше примере, если thread1 получит указатель до того, как thread2 вызовет erase , будет ли объект, на который указано, по-прежнему действительным?На самом деле он не будет удален после завершения thread1? Обратите внимание, что доступ к глобальному вектору будет осуществляться через критическую секцию.
Я думаю, что именно так работают shared_ptrs, но мне нужно быть уверенным.
Решение
Для обеспечения безопасности потоков boost::shared_ptr вам следует проверить эта ссылка.Это не гарантирует безопасность, но на многих платформах это работает.Изменение std::vector небезопасно, AFAIK.
Другие советы
В приведенном выше примере, если thread1 получит указатель до того, как thread2 вызовет erase , будет ли объект, на который указано, по-прежнему действительным?На самом деле он не будет удален после завершения thread1?
В вашем примере, если thread1 получает указатель перед thread2, то thread2 должен будет ждать в начале функции (из-за блокировки).Итак, да, объект, на который указано, по-прежнему будет действительным.Однако, возможно, вы захотите убедиться, что my_vec не является пустым, прежде чем обращаться к его первому элементу.
Если, кроме того, вы синхронизируете обращения к вектору (как в вашем исходном предложении raw pointer), ваше использование безопасно.В противном случае вы можете нарушить пример 4 по ссылке, предоставленной другим респондентом.