Есть ли boost:: weak_intrusive_pointer?
По старым причинам мне нужно использовать навязчивые указатели, так как мне нужно преобразовать необработанные указатели в интеллектуальные указатели.
Однако я заметил, что нет слабой интрузивной указатель для повышения. Я нашел разговор об этом в списке ускоренных тем, но ничего конкретного.
Кто-нибудь знает о потокобезопасной реализации слабого интрузивного указателя?
Спасибо
Рич
Ответы
Ответ 1
Это не имеет никакого смысла.
Чтобы уточнить: weak_ptr
указывает на тот же экземпляр объекта counter
, который выполняется shared_ptr
. Когда shared_ptr
выходит за пределы области видимости, экземпляр counter
остается (с эффективным счетом в 0), что позволяет экземплярам weak_ptr
проверять, что они эффективно указывают на освобожденный объект.
С Intrusive Counting счетчик встроен в объект. Когда счетчик достигнет 0, объект обычно либо перерабатывается, либо удаляется... но точка счетчика больше не доступна. Обоснование заключается в том, что это позволяет использовать более эффективное хранилище (1 отдельный блок) и большую скорость (локальность кэша).
Если вам нужен слабый подсчет ссылок и не заботятся о преимуществах интрузивного подсчета, вы можете использовать комбинацию shared_ptr
и weak_ptr
.
Идея состоит в том, чтобы отключить счетчик от объектов.
class Counted
{
// bla
private:
boost::shared_ptr<int> mCounter;
};
Теперь вы можете вернуть слабые ручки:
class WeakHandle
{
public:
explicit WeakHandle(Counted& c): mCounter(c.mCounter), mObject(&c) {}
bool expired() const { return mCounter.expired(); }
private:
boost::weak_ptr<int> mCounter;
Counted* mObject;
};
Здесь мы отделяем время жизни счетчика от времени жизни объекта, так что оно будет частично уничтожено разрушением объекта. Таким образом, возможно сделать weak_ptr
.
И, конечно, используя shared_ptr
и weak_ptr
, это Thread Safe;)
Ответ 2
Текущая реализация интрузивного указателя использует счетчик ссылок. Таким образом, удаление объекта delete также удаляет счетчик, поэтому weak_intrusive_pointer никогда не узнает, что объект был удален.
Если вам нужно получить weak_ptr из this
, вы, вероятно, выполните поиск boost::enable_shared_from_this<T>
.
Ответ 3
Мне не понравился ни один из предыдущих ответов, поэтому:
Нет, я не знаю о реализации, но я думаю, что это возможно. Стандартная реализация shared_ptr содержит два счетчика ссылок, один для "сильных" и один для "слабых" ссылок, а также указатель на референт. В реализации intrusive_ptr сильный счет должен быть частью объекта, но слабый не может быть. Итак, кажется, что вы можете создать "слабый" intrusive_ptr.
Определите слабый помощник указателя:
template<class X>
class intrusive_ptr_weak_helper {
long weak_ref_count;
X *target_instance;
};
Затем запишите это в объект рядом с подсчетом ссылок:
struct X {
...
intrusive_ptr_weak_helper *ref_weak_helper;
...
long ref_count;
...
};
При построении X:
ref_count = 0;
ref_weak_helper = NULL;
"Сильный" указатель intrusive_strong_ptr идентичен intrusive_ptr, пока не произойдет удаление. Когда сильное количество ссылок обращается в нуль (перед удалением):
if (ref_weak_helper != NULL) {
if (ref_weak_helper->weak_ref_count == 0)
delete ref_weak_helper;
else
ref_weak_helper->target_instance = NULL;
}
"Слабая" версия, intrusive_weak_ptr, записывает указатель на слабый помощник, обрабатывает этот счетчик ссылок и обращается к целевому объекту с помощью указателя target_instance. Когда значение weak_ref_count уменьшается до нуля, статус target_instance определяет, удаляется ли хелпер или нет.
Есть много отсутствующих деталей (например, проблемы с w390), но это смешение shared_ptr и intrusive_ptr. Он поддерживает основные преимущества intrusive_ptr (оптимизации кэша, повторное использование третьей партии навязчивого (сильный) кол-реф, сильные и слабые указатели дублёров являются указателем размера), добавляя дополнительную работу в основном в слабом опорном канале.