* Destructor: delete the list
*/
~CDList() throw(AssertionException) {
- T* list = d_list;
destroy();
- free(list);
+
+ if(d_callDestructor) {
+ for(unsigned i = 0; i < d_size; ++i) {
+ d_list[i].~T();
+ }
+ }
+
+ free(d_list);
}
/**
~CDMap() throw(AssertionException) {
// Delete all the elements and clear the map
- for(typename table_type::iterator
- i = d_map.begin(), iend = d_map.end(); i != iend; ++i) {
- /*
+ /*for(typename table_type::iterator
+ i = d_map.begin(), iend = d_map.end(); i != iend; ++i) {
+
delete (*i).second;
free((*i).second);
- */
- }
+
+ }*/
d_map.clear();
emptyTrash();
}
/**
* Destructor does nothing: subclass must explicitly call destroy() instead.
*/
- virtual ~ContextObj() {}
+ virtual ~ContextObj() { Debug("contextgc") << "context obj dest" << std::endl; }
/**
* If you want to allocate a ContextObj object on the heap, use this
* ContextMemoryManager as an argument.
*/
void deleteSelf() {
+ this->~ContextObj();
::operator delete(this);
}
if(ref_count) {
d_nv->dec();
}
- Assert(ref_count || d_nv->d_rc > 0,
+ Assert(ref_count ||
+ d_nv->d_rc > 0 ||
+ d_nv->isBeingDeleted(),
"Temporary node pointing to an expired node");
}
}
};
+struct NVReclaim {
+ NodeValue*& d_reclaimField;
+ NVReclaim(NodeValue*& reclaim) :
+ d_reclaimField(reclaim) {
+
+ Debug("gc") << ">> setting NVRECLAIM field\n";
+ }
+ ~NVReclaim() {
+ Debug("gc") << "<< clearing NVRECLAIM field\n";
+ d_reclaimField = NULL;
+ }
+};
+
void NodeManager::reclaimZombies() {
// FIXME multithreading
if(nv->getKind() != kind::VARIABLE) {
poolRemove(nv);
}
+ NVReclaim rc(d_underTheShotgun);
+ d_underTheShotgun = nv;
// remove attributes
d_attrManager.deleteAllAttributes(nv);
friend class NodeManagerScope;
friend class expr::NodeValue;
+ bool isCurrentlyDeleting(const expr::NodeValue *nv) const{
+ return d_underTheShotgun == nv;
+ }
+
+ expr::NodeValue* d_underTheShotgun;
+
bool d_reclaiming;
ZombieSet d_zombies;
NodeManager(context::Context* ctxt) :
d_attrManager(ctxt),
- d_reclaiming(false) {
+ d_underTheShotgun(NULL),
+ d_reclaiming(false)
+
+ {
poolInsert( &expr::NodeValue::s_null );
}
/** Decrement ref counts of children */
inline void decrRefCounts();
+ bool isBeingDeleted() const;
+
public:
template <bool ref_count>
}
inline void NodeValue::inc() {
+ Assert(!isBeingDeleted(),
+ "NodeValue is currently being deleted "
+ "and increment is being called on it. Don't Do That!");
// FIXME multithreading
if(EXPECT_TRUE( d_rc < MAX_RC )) {
++d_rc;
return d_children + d_nchildren;
}
+
+inline bool NodeValue::isBeingDeleted() const
+{
+ return NodeManager::currentNM() != NULL &&
+ NodeManager::currentNM()->isCurrentlyDeleting(this);
+}
+
}/* CVC4::expr namespace */
}/* CVC4 namespace */
*/
ECData(context::Context* context, TNode n);
+ ~ECData() { Debug("ufgc") << "Calling ECData destructor" << std::endl;}
+
/**
* An ECData takes over the watch list of another ECData.
* This is the second step in the union operator for ECData.