2010-10-27 10 views
1

J'ai une boucle for qui itère dans un document XML et trouve un attribut spécifié, le pointeur qui pointe vers le nœud courant se trouve dans un boost :: interprocess :: unique_ptr et possède un suppresseur personnalisé pour appelez la fonction release() de l'objet. Il semble qu'à chaque itération de boucle le pointeur est supprimé, mais la fonction release() se déclenche quand cela se produit.Suppression personnalisée de Unique_ptr, suppression contrôlée

Quelqu'un pourrait-il suggérer une solution? Je pensais à la mise en œuvre d'un mécanisme pour vérifier si elle doit être supprimée, mais je ne sais pas comment je ferais ça ...

code:

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... 
{ 

....

objets 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); 
    } 
} 

Deleter:

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

EDIT:

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


virtual DOMNode*   nextNode() = 0; 

Répondre

2

Je n'ai pas 2010 visuelle pour la compilation et le débogage au travail, sur ly à la maison. donc je ne peux pas être sûr. Mais franchement, je n'aime vraiment pas le concept que votre itérateur possède votre pointeur.

Votre collection possède le pointeur, mais pas l'itérateur! Ce n'est pas son rôle ..

En C++ 0x il y a un complément à shared_ptr qui est std :: weak_ptr que vous pouvez construire à partir de shared_ptr, ce qui permet de consulter et de modifier les données, mais n'ayant rien à voir avec la propriété, sauf devenir plus ou moins inaccessible lorsque le pointeur ajouté par le shared_ptr est libéré.

J'utiliserais une sorte de std :: weak_ptr pour vos itérateurs. Mais pour unique_ptr je suppose que c'est un simple pointeur sur vos données qui prend le rôle de référence faible.

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. 
} 
+0

donc si je comprends bien, le courant devrait être un weak_ptr et l'itérateur peut encore être un unique_ptr? –

+0

compilé avec VS2003, en utilisant boost, pas C++ 0x –

+0

désolé weak_ptr sont shared_ptr contrepartie, pas unique_ptr counter_part (J'ai modifié mon message). J'utiliserais un simple pointeur. –