Пользовательское удаление Unique_ptr, контролируемое удаление - PullRequest
1 голос
/ 27 октября 2010

У меня есть цикл for, который выполняет итерацию по документу XML и находит указанный атрибут, указатель, который указывает на текущий узел, находится внутри boost :: interprocess :: unique_ptr и имеет собственный обработчик для вызова объекта release()функция.Кажется, что на каждой итерации цикла указатель удаляется, но функция release() выдает, когда это происходит.

Может кто-нибудь предложить решение?Я думал о реализации механизма, чтобы проверить, должен ли он быть удален, но я не уверен, как бы я это сделал ...

Код:

typedef bi::unique_ptr<DOMNodeIterator, release_deleter> iterator_ptr;
typedef bi::unique_ptr<DOMNode, release_deleter> node_ptr;

iterator_ptr itera(document->createNodeIterator(rootelement, DOMNodeFilter::SHOW_ALL, NULL, true));

for(node_ptr current(itera->nextNode()); current != 0; current.reset(itera->nextNode())) // throws after one iteration...
{   

....

объекты release()

void DOMElementNSImpl::release()
{
    if (fNode.isOwned() && !fNode.isToBeReleased())
        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);  // throws here if released after each loop iteration

    DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
    if (doc) {
        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
        fParent.release();
        doc->release(this, DOMMemoryManager::ELEMENT_NS_OBJECT);
    }
    else {
        // shouldn't reach here
        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
    }
}

средство удаления:

struct release_deleter
{
    template <typename T>
    void operator()(T* pPtr) const
    {
        pPtr->release();
    }
};

РЕДАКТИРОВАТЬ:

virtual DOMNodeIterator *createNodeIterator(DOMNode* root,
                                            DOMNodeFilter::ShowType whatToShow,
                                            DOMNodeFilter* filter,
                                            bool entityReferenceExpansion) = 0;


virtual DOMNode*           nextNode() = 0;

1 Ответ

2 голосов
/ 27 октября 2010

У меня нет Visual 2010 для компиляции и отладки на работе, только дома.поэтому я не могу быть уверен.

Но, честно говоря, мне действительно не нравится концепция, что ваш итератор владеет вашим указателем.

Ваша коллекция владеет указателем, а итератор - нет!это не его роль ..

В C ++ 0x есть дополнение к shared_ptr, которое является std :: weak_ptr, которое вы можете построить из shared_ptr, позволяющее просматривать и изменять данные, но не имеющее ничего общего свладение, за исключением того, что он становится более или менее недоступным, когда освобождается указатель, добавленный shared_ptr.

Я бы использовал для ваших итераторов что-то вроде std :: weak_ptr.Но для unique_ptr я бы предположил, что это простой указатель на ваши данные, который играет роль слабой ссылки.

EDIT:

DOMNodeIterator * pIter = document->createNodeIterator(rootelement, DOMNodeFilter::SHOW_ALL, NULL, true);

if(pIter==NULL)
{
    return;
}

while(true) // be careful to infinite loops
{
    DOMNode * pNode = pIter->nextNode();
    if (pNode==NULL)
    {
        break;  
    }

    // ... your visiting the nodes here.
}
...