Homepage Demos Overview Downloads Tutorials Reference
Credits

WMclass.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 // David S. Touretzky
00003 #ifndef INCLUDED_WMclass_h_
00004 #define INCLUDED_WMclass_h_
00005 
00006 #include <string>
00007 #include <vector>
00008 #include <iostream>
00009 #include "Events/EventRouter.h"
00010 
00011 /*! @file
00012  *  @brief  Watchable memory.  Variables are monitored and changes are announced.
00013  *  @author dst (Creator)
00014  *  @author alokl (Ported)
00015  *  
00016  *  $Author: ejt $
00017  *  $Name: tekkotsu-2_2 $
00018  *  $Revision: 1.3 $
00019  *  $State: Rel $
00020  *  $Date: 2003/10/10 17:46:04 $
00021  *
00022  * \par These macros allow you to quickly create a WM variable, but only if
00023  * it's staticly defined - you can't use these with a dynamic number
00024  * of variables.  You'll have to manually create a WMitem<T> or
00025  * another subclass of WMitem_base if you want define these on the
00026  * fly... it's not hard to do, just look at the macro definitions.
00027  *
00028  * \par WMvar(type,name) declares the variable in the registry
00029  * GlobalWM.
00030  *
00031  * \par WMvari(type,name,initval) declares the variable in GlobalWM
00032  * and initializes it if it doesn't already exist.
00033  *
00034  * \par WMvar_(type,name,registry) declares the variable in the
00035  * specified registry.
00036  *
00037  * \par WMvari_(type,name,initval,registry) declares the variable in
00038  * the specified registry and initializes it if it doesn't already
00039  * exist.
00040  *
00041  * \par WMreg(name) declares a new WMregistry as a variable in
00042  * GlobalWM.
00043  *
00044  * \par WMreg(name,registry) declares a new WMregistry as a variable
00045  * in the specified registry,
00046  *
00047  * Examples:  
00048  * - WMvar(int, foo);  
00049  * - WMvari(double, head_angle, 37.5);  
00050  * - WMreg(myreg);<br>
00051  * - WMvar_(bool, winflag, myreg);
00052  */
00053 
00054 #define WM_max_stringlen 60   //!< Maximum displayed length of a char* or std::string variable.
00055 
00056 class WMentry;
00057 class WMitem_base;
00058 
00059 //================================================================
00060 
00061 //! A WMregistry is a namespace; it holds a collection of WMEntry instances describing the variables that live in this registry.
00062 class WMregistry {
00063 public:
00064   std::string name; //!< Name of the registry.
00065   std::vector<WMentry*> entries; //!< Entries that make up the registry.
00066   bool watched; //!< True if changes to this registry are being monitored.
00067   WMregistry* parent; //!< pointer to parent registry (allows recursive structure)
00068 
00069 public:
00070   //! Constructor
00071   WMregistry(const std::string &n = "anonymous", WMregistry* p=NULL) : name(n), entries(), watched(0), parent(p) {};
00072   WMregistry(const WMregistry& in) : name(in.name), entries(in.entries), watched(in.watched), parent(in.parent) {} //!< shallow copy
00073 
00074   //! shallow assignment
00075   WMregistry& operator=(const WMregistry& in) {
00076     name=in.name;
00077     entries=in.entries;
00078     watched=in.watched;
00079     parent=in.parent;
00080     return *this;
00081   }
00082 
00083   //! Turn on monitoring of changes to variables.
00084   void watch(void) { watched = 1; };
00085 
00086   //! Turn off monitoring of changes to variables.
00087   void unwatch(void) { watched = 0; };
00088 
00089   //! Dump the registry to the console, for debugging.
00090   void dump(void) const;
00091 
00092 };
00093 
00094 //================================================================
00095 
00096 //! A WMentry is an entry in a WMregistry.
00097 /*! The item it describes is a unique variable, which may be accessed
00098  *  via many WMitem instances, all of which point back to the same
00099  *  WMentry. */
00100 class WMentry {
00101 public:
00102   std::string const item_name; //!< Name of the variable described by this entry.
00103   std::string const type_name; //!< Type of the variable, e.g., "int".
00104   WMitem_base* const item; //!< Pointer to a WMitem instance for the variable.
00105   WMregistry* registry; //!< The registry in which this entry resides.
00106   bool watched;//!< True if changes to this variable should be reported.
00107 
00108 public:
00109   //! constructor
00110   WMentry(const std::string &iname, const std::string &tname, WMitem_base* ival, WMregistry* reg = 0) : 
00111     item_name(iname), type_name(tname), item(ival), registry(reg), watched(0) {};
00112   WMentry(const WMentry& in) : item_name(in.item_name), type_name(in.type_name), item(in.item), registry(in.registry), watched(in.watched) {} //!< shallow copy
00113 
00114 private:
00115   WMentry operator=(const WMentry&); //!< don't assign
00116 };
00117 
00118 
00119 //================================================================
00120 
00121 //! WMitem_base is the base class from which all WMitem<T> subclasses are derived.
00122 class WMitem_base {
00123 public:
00124   void* const         value;    //!< Pointer to the actual variable referenced by this WMitem.
00125   WMentry*            entry;    //!< Pointer to the WMentry describing this variable.
00126   virtual std::string toString(void) const = 0; //!< override this to return appropriate string representation
00127 
00128   //!Constructor
00129   WMitem_base(void* const val) : value(val), entry(NULL) {};
00130   WMitem_base(const WMitem_base &in ) : value(in.value), entry(in.entry) {} //!< *can* copy
00131 
00132   //! Turn on monitoring of changes to the variable described by this entry.
00133   void watch(void) const {
00134     entry->watched = 1; 
00135     erouter->postEvent(new EventBase(EventBase::wmVarEGID,reinterpret_cast<unsigned int>(entry),EventBase::activateETID));
00136   };
00137 
00138   //! Turn off monitoring of changes to the variable described by this entry.
00139   void unwatch(void) const {
00140     entry->watched = 0;
00141     erouter->postEvent(new EventBase(EventBase::wmVarEGID,reinterpret_cast<unsigned int>(entry),EventBase::deactivateETID));
00142   };
00143 
00144 private:
00145   WMitem_base& operator=(const WMitem_base & ); //!< don't assign
00146 };
00147 
00148 
00149 
00150 //! WMitem<T> is a reference to the variable of type T described by the associated WMentry
00151 /*! If the variable is declared in multiple functions, each
00152  *  declaration will have an associated WMitem<T> instance, but all
00153  *  the instances will reference the same variable. */
00154 template<class T>
00155 class WMitem : public WMitem_base {
00156 public:
00157   WMitem(T* const initval) : WMitem_base(initval)  {} //!< constructor
00158   WMitem(const WMitem& in) : WMitem_base(in) {} //!< shallow copy
00159 
00160   virtual WMitem<T>& operator= (const T &new_value); //!< Assignment operator.
00161   WMitem<T>& operator++ ();                  //!< Generic operator prefix (++x)
00162   WMitem<T>  operator++ (int);               //!< Generic operator postfix (x++)
00163   WMitem<T>& operator-- ();                  //!< Generic operator prefix (--x)
00164   WMitem<T>  operator-- (int);               //!< Generic operator postfix (x--)
00165   WMitem<T>& operator+= (const T &val);      //!< Generic operator+=
00166   WMitem<T>& operator-= (const T &val);      //!< Generic operator-=
00167   WMitem<T>& operator*= (const T &val);      //!< Generic operator*=
00168   WMitem<T>& operator/= (const T &val);      //!< Generic operator/=
00169   
00170   //! Annonces changes, throws an event from wmVarEGID
00171   void announce (const T &val);
00172   
00173   //! Explicit retrieval of variable value, used by toString()
00174   virtual T& get_value(void) const { return *static_cast<T*>(value); };
00175   
00176   //! Coerce a WMitem<T> to type T by retrieving the value.
00177   virtual operator T&() const { return  *static_cast<T*>(value); };
00178   
00179   //! std::String representation of the value.
00180   virtual std::string toString(void) const;    
00181 };
00182 
00183 
00184 //================================================================
00185 
00186 //!Allows you to create a static WMvar
00187 #define WMvar(T,name) \
00188   static WMitem<T> name(lookup_WMentry<T>(#name,#T,GlobalWM));
00189 
00190 //!Allows you to create a static WMvar with a default initialization value
00191 #define WMvari(T,name,initval) \
00192   static WMitem<T> name(lookup_WMentry<T>(#name,#T,initval,GlobalWM));
00193 
00194 //!Allows you to create a static WMvar in a registry with a default initialization value
00195 #define WMvar_(T,name,registry) \
00196   static WMitem<T> name(lookup_WMentry<T>(#name,#T,registry));
00197 
00198 //!Allows you to create a static WMvar in a registry with a default initialization value
00199 #define WMvari_(T,name,initval,registry) \
00200   static WMitem<T> name(lookup_WMentry<T>(#name,#T,initval,registry));
00201 
00202 //!Allows you to create a new static registry
00203 #define WMreg(name) \
00204   static WMitem<WMregistry> name(lookup_reg(#name,GlobalWM));
00205 
00206 //!Allows you to create a new static registry with a parent registry
00207 #define WMreg_(name,parent) \
00208   static WMitem<WMregistry> name(lookup_reg(#name,parent));
00209 
00210 //================================================================
00211 
00212 
00213 
00214 //! Three versions of lookup_WMentry with different argument types, and one version of create_WMentry, which they share.  
00215 //!@name Global Lookup functions
00216 
00217 //! The lookup_reg function is defined in WMclass.cc since it's not templated.
00218 template<typename T>
00219 WMitem<T> lookup_WMentry(const std::string &iname,
00220                          const std::string &tname,
00221                          const std::string &regname);
00222 
00223 template<typename T>
00224 WMitem<T> lookup_WMentry(const std::string &iname,
00225                          const std::string &tname, 
00226                          const WMregistry &reg);
00227 
00228 template<typename T>
00229 WMitem<T> lookup_WMentry(const std::string &iname,
00230                          const std::string &tname,
00231                          const T &initval, WMregistry &reg);
00232 
00233 template<typename T>
00234 WMitem<T> create_WMentry(const std::string &iname, 
00235                          const std::string &tname, 
00236                          const T* const value, WMregistry &reg);
00237 
00238 //! the global registry for all others to put their stuff in
00239 extern WMregistry GlobalWM;
00240 
00241 WMitem<WMregistry> lookup_reg(const std::string &name, WMregistry &registry);
00242 
00243 void dump(const WMitem<WMregistry> &wmreg);
00244 
00245 //@}
00246 
00247 /*! Generic toString() method that just displays the variable's type and
00248  *  address.  Will be overridden for common types like int or double. */
00249 template<class T>
00250 std::string WMitem<T>::toString(void) const {
00251   char print_buffer[30];
00252   sprintf(print_buffer,"%x",reinterpret_cast<unsigned int>(value));
00253   return "<" + entry->type_name + " at 0x" + print_buffer + ">";
00254 }
00255 
00256 /*! The assignment operator for WMitem<T> changes the value of the
00257  *  variable referenced by the WMitem, and reports the change if the
00258  *  variable is "watched". */
00259 template<class T>
00260 WMitem<T>& WMitem<T>::operator= (const T &new_value) {
00261   get_value() = new_value;
00262   //  *static_cast<T*>(value)=new_value;
00263   announce (new_value);
00264   return *this;
00265 }
00266 
00267 template<class T>
00268 void WMitem<T>::announce (const T&) {
00269   if (entry->watched) {
00270     erouter->postEvent(new EventBase(EventBase::wmVarEGID,reinterpret_cast<unsigned int>(entry),EventBase::statusETID));
00271   }
00272   /*    if (wmMonitorBehavior!=NULL) {
00273         std::string s(entry->item_name);
00274         WMregistry *temp=entry->registry;
00275         while (temp!=&GlobalWM && temp!=NULL) {
00276         s=temp->name + "." + s;
00277         temp=temp->parent;
00278         }
00279         wmMonitorBehavior->report(entry->type_name, s, toString());
00280         }
00281   */
00282   /*
00283     if (entry->registry->watched)
00284     if (wmMonitorBehavior!=NULL)
00285     wmMonitorBehavior->report(entry->registry->name, "registry_change",
00286     "change to var");
00287   */
00288 }
00289 
00290 template<class T>
00291 WMitem<T>& WMitem<T>::operator++ (void) {
00292   announce(++get_value());
00293   return *this;
00294 }
00295 
00296 template<class T>
00297 WMitem<T> WMitem<T>::operator++ (int) {
00298   WMitem<T> temp(*this);
00299   announce(++get_value());
00300   return temp;
00301 }
00302 
00303 template<class T>
00304 WMitem<T>& WMitem<T>::operator-- (void) {
00305   announce(--get_value());
00306   return *this;
00307 }
00308 
00309 template<class T>
00310 WMitem<T> WMitem<T>::operator-- (int) {
00311   WMitem<T> temp(*this);
00312   announce(--get_value());
00313   return temp;
00314 }
00315 
00316 template<class T>
00317 WMitem<T>& WMitem<T>::operator+= (const T &val) {
00318   return operator=(get_value()+val);
00319 }
00320 
00321 template<class T>
00322 WMitem<T>& WMitem<T>::operator-= (const T &val) {
00323   return operator=(get_value()-val);
00324 }
00325 
00326 template<class T>
00327 WMitem<T>& WMitem<T>::operator*= (const T &val) {
00328   return operator=(get_value()*val);
00329 }
00330 
00331 template<class T>
00332 WMitem<T>& WMitem<T>::operator/= (const T &val) {
00333   return operator=(get_value()/val);
00334 }
00335 
00336 //================================================================
00337 //
00338 // Three versions of lookup_WMentry with different argument types,
00339 // and one version of create_WMentry, which they share.  
00340 //
00341 // The lookup_reg function is defined in WMclass.c since it's not
00342 // templated.
00343 
00344 template<typename T>
00345 WMitem<T> lookup_WMentry(const std::string &iname,
00346                          const std::string &tname,
00347                          const std::string &regname) {
00348   WMregistry* reg = 0;
00349   for (std::vector<WMentry*>::const_iterator it = GlobalWM.entries.begin(); it != GlobalWM.entries.end(); it++) {
00350     if ( (*it)->item_name == regname ) {
00351       reg = static_cast<WMregistry*>((*it)->item->value);
00352       break;
00353     };
00354   };
00355   if ( reg == 0 ) {
00356     reg = new WMregistry(regname, &GlobalWM);
00357     create_WMentry(regname, "WMregistry", reg, GlobalWM);
00358   };
00359   return lookup_WMentry<T>(iname, tname, *reg);
00360 }
00361 
00362 template<typename T>
00363 WMitem<T> lookup_WMentry(const std::string &iname,
00364                          const std::string &tname, 
00365                          WMregistry &reg) {
00366   for (std::vector<WMentry*>::const_iterator it = reg.entries.begin(); it != reg.entries.end(); it++) {
00367     if ( (*it)->item_name == iname )
00368       return *static_cast<WMitem<T> const*>((*it)->item);
00369   };
00370   return create_WMentry(iname, tname, new T, reg);
00371 }
00372 
00373 template<typename T>
00374 WMitem<T> lookup_WMentry(const std::string &iname,
00375                          const std::string &tname,
00376                          T const &initval, WMregistry &reg) {
00377   for (std::vector<WMentry*>::const_iterator it = reg.entries.begin(); it != reg.entries.end(); it++) {
00378     if ( (*it)->item_name == iname )
00379       return *static_cast<WMitem<T> const*>((*it)->item);
00380   };
00381   return create_WMentry(iname, tname, new T(initval), reg);
00382 }
00383  
00384 template<typename T>
00385 WMitem<T> create_WMentry(const std::string &iname, 
00386                          const std::string &tname, 
00387                          T* const value, WMregistry &reg) {
00388   WMentry* new_entry = new WMentry(iname, tname, new WMitem<T>(value), &reg);
00389   new_entry->item->entry = new_entry;
00390   reg.entries.push_back(new_entry);
00391   return *static_cast<WMitem<T> const*>(new_entry->item);
00392 }
00393 
00394 #endif
00395 

Tekkotsu v2.2
Generated Tue Oct 19 14:19:16 2004 by Doxygen 1.3.9.1