smartcdo.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file smartcdo.h
00004  *\brief Smart context-dependent object wrapper
00005  *
00006  * Author: Clark Barrett
00007  *
00008  * Created: Fri Nov 12 17:28:58 2004
00009  *
00010  * <hr>
00011  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  * 
00027  */
00028 /*****************************************************************************/
00029 
00030 #ifndef _cvcl__include__smartcdo_h_
00031 #define _cvcl__include__smartcdo_h_
00032 
00033 #include "cdo.h"
00034 
00035 namespace CVCL {
00036 
00037 /*****************************************************************************/
00038 /*!
00039  *\class SmartCDO
00040  *\brief SmartCDO
00041  *
00042  * Author: Clark Barrett
00043  *
00044  * Created: Fri Nov 12 17:33:31 2004
00045  *
00046  * Wrapper for CDO which automatically allocates and deletes a pointer to a
00047  * CDO.  This allows the copy constructor and operator= to be defined which are
00048  * especially useful for storing CDO's in vectors.  All operations are const to
00049  * enable use as a member of CDLists.
00050  *
00051  * Be careful not to delete RefCDO during pop(), since this messes up
00052  * the backtracking data structures.  We delay the deletion by
00053  * registering each RefCDO to be notified before and after each pop().
00054  * This makes the use of SmartCDO somewhat more expensive, so use it
00055  * with care.
00056  * 
00057  */
00058 /*****************************************************************************/
00059 template <class T>
00060 class SmartCDO {
00061 
00062   template <class U>
00063   class RefCDO {
00064     friend class SmartCDO;
00065     int d_refCount;
00066     CDO<U> d_cdo;
00067     bool d_delay; //!< Whether to delay our own deletion
00068 
00069     class RefNotifyObj : public ContextNotifyObj {
00070       friend class RefCDO<U>;
00071       RefCDO<U>* d_ref;
00072       //! Constructor
00073       RefNotifyObj(RefCDO<U>* ref, Context* context)
00074         : ContextNotifyObj(context), d_ref(ref) { }
00075       void notifyPre() { d_ref->d_delay = true; }
00076       void notify() {
00077         d_ref->d_delay = false;
00078         d_ref->kill();
00079       }
00080     };
00081 
00082     RefNotifyObj* d_notifyObj;
00083 
00084     friend class RefNotifyObj;
00085 
00086     RefCDO(Context* context): d_refCount(0), d_cdo(context), d_delay(false),
00087       d_notifyObj(new RefNotifyObj(this, context)) {}
00088 
00089     RefCDO(Context* context, const U& cdo, int scope = -1)
00090       : d_refCount(0), d_cdo(context, cdo, scope), d_delay(false),
00091       d_notifyObj(new RefNotifyObj(this, context)) {}
00092 
00093     ~RefCDO() { delete d_notifyObj; }
00094     //! Delete itself, unless delayed (then we'll be called again later)
00095     void kill() { if(d_refCount==0 && !d_delay) delete this; }
00096   };
00097 
00098   RefCDO<T>* d_data;
00099 
00100 public:
00101   //! Check if the SmartCDO object is Null
00102   bool isNull() const { return (d_data==NULL); }
00103   //! Default constructor: create a Null SmartCDO object
00104   SmartCDO(): d_data(NULL) { }
00105   //! Create and initialize SmartCDO object at the current scope
00106   SmartCDO(Context* context)
00107     { d_data = new RefCDO<T>(context); d_data->d_refCount++; }
00108   //! Create and initialize SmartCDO object at the given scope
00109   SmartCDO(Context* context, const T& data, int scope = -1)
00110     { d_data = new RefCDO<T>(context, data, scope); d_data->d_refCount++; }
00111   //! Delete 
00112   ~SmartCDO()
00113     { if (isNull()) return;
00114       if (--d_data->d_refCount == 0) d_data->kill(); }
00115 
00116   SmartCDO(const SmartCDO<T>& cdo) : d_data(cdo.d_data)
00117     { if (!isNull()) d_data->d_refCount++; }
00118 
00119   SmartCDO<T>& operator=(const SmartCDO<T>& cdo)
00120   {
00121     if (this == &cdo) return *this;
00122     if (!isNull() && --(d_data->d_refCount)) d_data->kill();
00123     d_data = cdo.d_data;
00124     if (!isNull()) ++(d_data->d_refCount);
00125     return *this;
00126   }
00127 
00128   void set(const T& data, int scope=-1) const {
00129     DebugAssert(!isNull(), "SmartCDO::set: we are Null");
00130     d_data->d_cdo.set(data, scope);
00131   }
00132   const T& get() const {
00133     DebugAssert(!isNull(), "SmartCDO::get: we are Null");
00134     return d_data->d_cdo.get();
00135   }
00136   operator T() const { return get(); }
00137   const SmartCDO<T>& operator=(const T& data) const {set(data); return *this;}
00138 };
00139 
00140 }
00141 
00142 #endif

Generated on Thu Apr 13 16:57:33 2006 for CVC Lite by  doxygen 1.4.4