Обратите внимание: эти сборки предназначены для сборок VS2008 / VS2010. Я не могу использовать какие-либо 11 конструкций.
Представьте, что у меня есть подписчики, слушающие какого-то издателя. У моего издателя есть контейнер с указателями подписчиков. В моем void detach (ISubscriber *) вместо блокировки списка подписчиков я вычеркну указатель NULL из-за отсутствия лучшего слова для этого подписчика.
//My container in the publisher. Inserts to not invalidate, removals only invalidate iterators pointing to the removed element, for this reason we NULL
Container<ISubscriber *> myContainer;
Now in the publisher...
void NotifySubscribers(){
foreach(subscriber in container){
if(subscriber)//This is my problem
subscriber->notify()
}
}
Строка 3 — указатель проверен и указывает на действительный объект.
Перед выполнением строки 4 другой поток обнуляет подписчика.
Линия 4 — Стрела.
Мой вопрос, есть ли способ, которым я могу использовать что-то вроде Interlocked, чтобы тест и вызов были атомарными.
например для объекта с подсчетом ссылок в деструкторе, что-то вроде этого работает
RefCountObject::~RefCountObject(){
if(InterlockedDecrement(&m_count) == 0)
delete m_data;
}
Здесь счетчик ссылок уменьшается автоматически и проверяется на ноль автоматически, тогда и только тогда, если он равен нулю, данные освобождаются.
Есть ли способ сделать это для вызова функции, основанной на достоверности указателя?
Изменить 1: Мне нужно уточнить немного на основе комментариев и спасибо за ваши ответы. Издатель не несет ответственности за «освобождение памяти» Подписчиков, поэтому утечки не будет. После уведомления издатель проходит цикл, который очищает контейнер, удаляя исключенных подписчиков.
Теперь что касается самих подписчиков. Когда они отрываются, они просто отрываются от прослушивания издателем. Они сами будут жить в статических объектах (это контракт, который нам требуется). Зачем? Потому что мы не можем позволить себе удерживать блокировку во время уведомления. Единственным другим вариантом было использование Share_Ptr, который было решено не включать в эту DLL из-за управления версиями в будущем.
Я создал рукописный shared_ptr, но потом мне пришло в голову, что любая ссылка на объект, который не был обернут в класс управления ресурсами, попадет в ту же ловушку и просто выдвинет «требование», что подписчики должны будут обязательно не делать ссылаться на любые висячие ссылки в рамках своей реализации указанного абонента.
Что возвращает нас к простому утверждению, что подписчики не могут быть «освобождены», и в настоящее время все клиенты, которые будут использовать это, являются статическими объектами. Мы просто смотрели в будущее. Некоторые пользователи являются унаследованными приложениями, и их было бы нелегко ввести enabled_shared_from_this и т.д.
Есть ли способ, которым я могу использовать что-то вроде Interlocked, чтобы тест и вызов были атомарными.
Для теста да будет способ. Вы просто хотите сравнить указатель.
Чтобы сделать звонок, я сомневаюсь в этом. Во время разговора вам понадобится охрана, то есть критическая секция.
Вы можете использовать стратегию «умного указателя» для отсроченного обнуления указателя. До тех пор, пока кто-то имеет ссылку на указатель, что определяется по количеству заблокированных ссылок, сохраняйте указатель действительным; когда счетчик обнуляется, можно обнулить.