#c #pointers #boost #shared
#c #указатели #повышение #общий
Вопрос:
Я столкнулся с проблемой, когда я не могу избавиться от последнего общего указателя, и мне это действительно нужно.
Итак, у меня есть менеджер и несколько рабочих потоков. Менеджер хранит коллекцию общих указателей на разные ресурсы. Работник может запросить у менеджера общий указатель на ресурс. Всегда будет 1 или более рабочих с общим указателем на ресурс. Моя конечная цель состоит в том, чтобы, когда все рабочие закончили с ресурсом, ресурс был удален. Однако в этой схеме менеджер всегда поддерживает общий указатель на ресурс, поэтому, даже если на общем указателе нет рабочих, ресурс не будет удален b / c счетчик ссылок всегда должен быть не менее 1, поскольку менеджер висит на нем. Мне нужно, чтобы менеджер зависал на общем указателе на ссылку, чтобы, если какой-либо работник попросит общий указатель, менеджер сможет его предоставить.
редактировать: когда ресурс создается, у работника он уже есть. Таким образом, при его создании его количество ссылок должно быть равно двум (оно есть у менеджера, и оно есть у одного работника). Когда счетчик ссылок достигает единицы (он есть только у менеджера), я бы хотел, чтобы он был удален. Если ресурс уже был удален и его ищет рабочий, ресурс должен быть воссоздан заново.
правка2: некоторый код:
SomeSharedPointer Manager::getResource(String unique_id)
{ // if unique id exists, return its mapped shared pointer, if unique id doesn't exist, create the resource, assign it a shared pointer, and stick it in the map
}
class Worker
{
SomeSharedPointer my_sp;
Worker()
{
String someUniqueId = "http://blah.com"
my_sp = Manager::getResource(someUniqueId);
// do some work on the resource
}
~Worker()
{
my_sp.reset(); // done with resource
}
}
Комментарии:
1. Вам необходимо предоставить некоторый исходный код, чтобы продемонстрировать, как вы работаете с
shared_ptr
s.2. A. см. weak_ptr B. вы не должны удалять общие указатели. Объекты, на которые указывает общий указатель, будут удалены
3. @sehe: да, я не удаляю сам общий указатель.
Ответ №1:
Почему менеджер хранит shared_ptr
(строгую ссылку) на объект, если ему не нужно сохранять контроль, а только передавать его? Не видя вашего кода, кажется, что менеджер удерживает a weak_ptr
, а затем передает его работникам, которые фиксируют его в a shared_ptr
на своем конце. Это позволит менеджеру передавать ссылки, не владея ни одной из своих собственных.
class Worker
{
SomeSharedPointer my_sp;
Worker()
{
String someUniqueId = "http://blah.com"
weak_ptr wp = Manager::getResource(someUniqueId);
my_sp = wp.lock();
// do some work on the resource
}
~Worker()
{
//my_sp.reset(); // handled automatically, as part of how shared pointers work
}
}
Если рабочий завершит и освободит ресурс, он будет уничтожен, и менеджер больше не сможет раздавать ссылки (которые можно протестировать getResource
и перезагрузить). Это кажется не совсем оптимальным, но является частью вашего дизайна, поэтому он должен работать так хорошо.
Редактировать: вы также могли бы getResource
вернуть общий указатель и попросить менеджера удерживать слабый указатель, попытаться заблокировать, выполнить внутреннюю проверку / перезагрузку, а затем вернуть общий указатель. Поскольку weak_ptr
s не могут быть созданы напрямую, это может работать несколько лучше.
С другой стороны, вы могли бы предоставить функцию, дополняющую ту, которая предоставляет рабочим указатель, который освобождает его и выполняет проверку количества в диспетчере.
Комментарии:
1. не зная слишком много о слабых указателях, это звучит как то, что мне нужно — тип указателя, который не имеет права собственности и не влияет на количество ссылок…
2. Это и есть слабые указатели, они сохраняют счетчик ссылок и могут предоставлять общие указатели (после проверки), но сами не владеют объектом и поэтому не учитываются как ссылки.
3. Что вы имели в виду в своем редактировании, что оно кажется не совсем оптимальным в том виде, в каком я его получил? Чтобы объяснить дальше, я удаляю ресурсы, когда рабочие с этим закончили, потому что это может быть случай, когда рабочие не используют ресурс в течение длительных периодов времени. Поэтому я думаю, что я бы хотел удалить ресурс до тех пор, пока другой работник не запросит его снова. Чтобы сделать пример более конкретным, я открываю сетевые подключения для этих работников. Я не хочу хранить около тонны открытых подключений, когда их не используют работники.
4. Перезагрузка в любое время, когда ресурс не используется, звучит так, как будто это может замедлиться, но, не зная, с чем вы работаете, я действительно понятия не имею. При сетевых подключениях было бы лучше позволить им удаляться, чтобы этот бит можно было игнорировать.
Ответ №2:
Используйте слабый указатель в диспетчере и общий указатель в рабочих, когда рабочий приходит с запросом указателя, создайте общий указатель, используя метод блокировки.
как в boost::shared_ptr fptr = weakfoo.lock();
если общий указатель пуст, указатель либо был выпущен последним работником, либо еще не создан и нуждается в создании
Я бы определенно избегал любых решений, связанных с просмотром количества ссылок… последует только боль 🙂
Ответ №3:
Я думаю, что ключевым является следующее:
Мне нужно, чтобы менеджер зависал на общем указателе на ссылку, чтобы, если какой-либо работник попросит общий указатель, менеджер сможет его предоставить.
Вам нужно решить, в какой момент больше рабочие не смогут запрашивать общий указатель. Как только вы узнаете, что это так, мастер может просто сбросить свой экземпляр общего указателя, тем самым освободив ссылку.