/*****************************************************************************/
/*!
*\file smartcdo.h
*\brief Smart context-dependent object wrapper
*
* Author: Clark Barrett
*
* Created: Fri Nov 12 17:28:58 2004
*
*
*
* License to use, copy, modify, sell and/or distribute this software
* and its documentation for any purpose is hereby granted without
* royalty, subject to the terms and conditions defined in the \ref
* LICENSE file provided with this distribution.
*
*
*
*/
/*****************************************************************************/
#ifndef _cvc3__include__smartcdo_h_
#define _cvc3__include__smartcdo_h_
#include "cdo.h"
namespace CVC3 {
/*****************************************************************************/
/*!
*\class SmartCDO
*\brief SmartCDO
*
* Author: Clark Barrett
*
* Created: Fri Nov 12 17:33:31 2004
*
* Wrapper for CDO which automatically allocates and deletes a pointer to a
* CDO. This allows the copy constructor and operator= to be defined which are
* especially useful for storing CDO's in vectors. All operations are const to
* enable use as a member of CDLists.
*
* Be careful not to delete RefCDO during pop(), since this messes up
* the backtracking data structures. We delay the deletion by
* registering each RefCDO to be notified before and after each pop().
* This makes the use of SmartCDO somewhat more expensive, so use it
* with care.
*
*/
/*****************************************************************************/
template
class SmartCDO {
template
class RefCDO {
friend class SmartCDO;
unsigned d_refCount;
CDO d_cdo;
bool d_delay; //!< Whether to delay our own deletion
class RefNotifyObj : public ContextNotifyObj {
friend class RefCDO;
RefCDO* d_ref;
//! Constructor
RefNotifyObj(RefCDO* ref, Context* context)
: ContextNotifyObj(context), d_ref(ref) { }
void notifyPre() { d_ref->d_delay = true; }
void notify() {
d_ref->d_delay = false;
d_ref->kill();
}
};
RefNotifyObj* d_notifyObj;
friend class RefNotifyObj;
RefCDO(Context* context): d_refCount(0), d_cdo(context), d_delay(false),
d_notifyObj(new RefNotifyObj(this, context)) {}
RefCDO(Context* context, const U& cdo, int scope = -1)
: d_refCount(0), d_cdo(context, cdo, scope), d_delay(false),
d_notifyObj(new RefNotifyObj(this, context)) {}
~RefCDO() { delete d_notifyObj; }
//! Delete itself, unless delayed (then we'll be called again later)
void kill() { if(d_refCount==0 && !d_delay) delete this; }
};
RefCDO* d_data;
public:
//! Check if the SmartCDO object is Null
bool isNull() const { return (d_data==NULL); }
//! Default constructor: create a Null SmartCDO object
SmartCDO(): d_data(NULL) { }
//! Create and initialize SmartCDO object at the current scope
SmartCDO(Context* context)
{ d_data = new RefCDO(context); d_data->d_refCount++; }
//! Create and initialize SmartCDO object at the given scope
SmartCDO(Context* context, const T& data, int scope = -1)
{ d_data = new RefCDO(context, data, scope); d_data->d_refCount++; }
//! Delete
~SmartCDO()
{ if (isNull()) return;
if (--d_data->d_refCount == 0) d_data->kill(); }
SmartCDO(const SmartCDO& cdo) : d_data(cdo.d_data)
{ if (!isNull()) d_data->d_refCount++; }
SmartCDO& operator=(const SmartCDO& cdo)
{
if (this == &cdo) return *this;
if (!isNull() && --(d_data->d_refCount)) d_data->kill();
d_data = cdo.d_data;
if (!isNull()) ++(d_data->d_refCount);
return *this;
}
void set(const T& data, int scope=-1) const {
DebugAssert(!isNull(), "SmartCDO::set: we are Null");
d_data->d_cdo.set(data, scope);
}
const T& get() const {
DebugAssert(!isNull(), "SmartCDO::get: we are Null");
return d_data->d_cdo.get();
}
operator T() const { return get(); }
const SmartCDO& operator=(const T& data) const {set(data); return *this;}
};
}
#endif