Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
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-4_0 $
00018  *  $Revision: 1.7 $
00019  *  $State: Exp $
00020  *  $Date: 2006/09/11 23:05:15 $
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   virtual ~WMitem_base() {} //!< destructor, does nothing
00125   void* const         value;    //!< Pointer to the actual variable referenced by this WMitem.
00126   WMentry*            entry;    //!< Pointer to the WMentry describing this variable.
00127   virtual std::string toString(void) const = 0; //!< override this to return appropriate string representation
00128 
00129   //!Constructor
00130   WMitem_base(void* const val) : value(val), entry(NULL) {};
00131   WMitem_base(const WMitem_base &in ) : value(in.value), entry(in.entry) {} //!< *can* copy
00132 
00133   //! Turn on monitoring of changes to the variable described by this entry.
00134   void watch(void) const {
00135     entry->watched = 1; 
00136     erouter->postEvent(EventBase::wmVarEGID,reinterpret_cast<size_t>(entry),EventBase::activateETID);
00137   };
00138 
00139   //! Turn off monitoring of changes to the variable described by this entry.
00140   void unwatch(void) const {
00141     entry->watched = 0;
00142     erouter->postEvent(EventBase::wmVarEGID,reinterpret_cast<size_t>(entry),EventBase::deactivateETID);
00143   };
00144 
00145 private:
00146   WMitem_base& operator=(const WMitem_base & ); //!< don't assign
00147 };
00148 
00149 
00150 
00151 //! WMitem<T> is a reference to the variable of type T described by the associated WMentry
00152 /*! If the variable is declared in multiple functions, each
00153  *  declaration will have an associated WMitem<T> instance, but all
00154  *  the instances will reference the same variable. */
00155 template<class T>
00156 class WMitem : public WMitem_base {
00157 public:
00158   WMitem(T* const initval) : WMitem_base(initval)  {} //!< constructor
00159   WMitem(const WMitem& in) : WMitem_base(in) {} //!< shallow copy
00160 
00161   virtual WMitem<T>& operator= (const T &new_value); //!< Assignment operator.
00162   WMitem<T>& operator++ ();                  //!< Generic operator prefix (++x)
00163   WMitem<T>  operator++ (int);               //!< Generic operator postfix (x++)
00164   WMitem<T>& operator-- ();                  //!< Generic operator prefix (--x)
00165   WMitem<T>  operator-- (int);               //!< Generic operator postfix (x--)
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   WMitem<T>& operator/= (const T &val);      //!< Generic operator/=
00170   
00171   //! Annonces changes, throws an event from wmVarEGID
00172   void announce (const T &val);
00173   
00174   //! Explicit retrieval of variable value, used by toString()
00175   virtual T& get_value(void) const { return *static_cast<T*>(value); };
00176   
00177   //! Coerce a WMitem<T> to type T by retrieving the value.
00178   virtual operator T&() const { return  *static_cast<T*>(value); };
00179   
00180   //! std::String representation of the value.
00181   virtual std::string toString(void) const;    
00182 };
00183 
00184 
00185 //================================================================
00186 
00187 //!Allows you to create a static WMvar
00188 #define WMvar(T,name) \
00189   static WMitem<T> name(lookup_WMentry<T>(#name,#T,GlobalWM));
00190 
00191 //!Allows you to create a static WMvar with a default initialization value
00192 #define WMvari(T,name,initval) \
00193   static WMitem<T> name(lookup_WMentry<T>(#name,#T,initval,GlobalWM));
00194 
00195 //!Allows you to create a static WMvar in a registry with a default initialization value
00196 #define WMvar_(T,name,registry) \
00197   static WMitem<T> name(lookup_WMentry<T>(#name,#T,registry));
00198 
00199 //!Allows you to create a static WMvar in a registry with a default initialization value
00200 #define WMvari_(T,name,initval,registry) \
00201   static WMitem<T> name(lookup_WMentry<T>(#name,#T,initval,registry));
00202 
00203 //!Allows you to create a new static registry
00204 #define WMreg(name) \
00205   static WMitem<WMregistry> name(lookup_reg(#name,GlobalWM));
00206 
00207 //!Allows you to create a new static registry with a parent registry
00208 #define WMreg_(name,parent) \
00209   static WMitem<WMregistry> name(lookup_reg(#name,parent));
00210 
00211 //================================================================
00212 
00213 
00214 
00215 //! Three versions of lookup_WMentry with different argument types, and one version of create_WMentry, which they share.  
00216 //!@name Global Lookup functions
00217 
00218 //! The lookup_reg function is defined in WMclass.cc since it's not templated.
00219 template<typename T>
00220 WMitem<T> lookup_WMentry(const std::string &iname,
00221                          const std::string &tname,
00222                          const std::string &regname);
00223 
00224 template<typename T>
00225 WMitem<T> lookup_WMentry(const std::string &iname,
00226                          const std::string &tname, 
00227                          const WMregistry &reg);
00228 
00229 template<typename T>
00230 WMitem<T> lookup_WMentry(const std::string &iname,
00231                          const std::string &tname,
00232                          const T &initval, WMregistry &reg);
00233 
00234 template<typename T>
00235 WMitem<T> create_WMentry(const std::string &iname, 
00236                          const std::string &tname, 
00237                          const T* const value, WMregistry &reg);
00238 
00239 //! the global registry for all others to put their stuff in
00240 extern WMregistry GlobalWM;
00241 
00242 WMitem<WMregistry> lookup_reg(const std::string &name, WMregistry &registry);
00243 
00244 void dump(const WMitem<WMregistry> &wmreg);
00245 
00246 //@}
00247 
00248 /*! Generic toString() method that just displays the variable's type and
00249  *  address.  Will be overridden for common types like int or double. */
00250 template<class T>
00251 std::string WMitem<T>::toString(void) const {
00252   char print_buffer[30];
00253   sprintf(print_buffer,"%p",value);
00254   return "<" + entry->type_name + " at 0x" + print_buffer + ">";
00255 }
00256 
00257 /*! The assignment operator for WMitem<T> changes the value of the
00258  *  variable referenced by the WMitem, and reports the change if the
00259  *  variable is "watched". */
00260 template<class T>
00261 WMitem<T>& WMitem<T>::operator= (const T &new_value) {
00262   get_value() = new_value;
00263   //  *static_cast<T*>(value)=new_value;
00264   announce (new_value);
00265   return *this;
00266 }
00267 
00268 template<class T>
00269 void WMitem<T>::announce (const T&) {
00270   if (entry->watched) {
00271     erouter->postEvent(EventBase::wmVarEGID,reinterpret_cast<size_t>(entry),EventBase::statusETID);
00272   }
00273   /*    if (wmMonitorBehavior!=NULL) {
00274         std::string s(entry->item_name);
00275         WMregistry *temp=entry->registry;
00276         while (temp!=&GlobalWM && temp!=NULL) {
00277         s=temp->name + "." + s;
00278         temp=temp->parent;
00279         }
00280         wmMonitorBehavior->report(entry->type_name, s, toString());
00281         }
00282   */
00283   /*
00284     if (entry->registry->watched)
00285     if (wmMonitorBehavior!=NULL)
00286     wmMonitorBehavior->report(entry->registry->name, "registry_change",
00287     "change to var");
00288   */
00289 }
00290 
00291 template<class T>
00292 WMitem<T>& WMitem<T>::operator++ (void) {
00293   announce(++get_value());
00294   return *this;
00295 }
00296 
00297 template<class T>
00298 WMitem<T> WMitem<T>::operator++ (int) {
00299   WMitem<T> temp(*this);
00300   announce(++get_value());
00301   return temp;
00302 }
00303 
00304 template<class T>
00305 WMitem<T>& WMitem<T>::operator-- (void) {
00306   announce(--get_value());
00307   return *this;
00308 }
00309 
00310 template<class T>
00311 WMitem<T> WMitem<T>::operator-- (int) {
00312   WMitem<T> temp(*this);
00313   announce(--get_value());
00314   return temp;
00315 }
00316 
00317 template<class T>
00318 WMitem<T>& WMitem<T>::operator+= (const T &val) {
00319   return operator=(get_value()+val);
00320 }
00321 
00322 template<class T>
00323 WMitem<T>& WMitem<T>::operator-= (const T &val) {
00324   return operator=(get_value()-val);
00325 }
00326 
00327 template<class T>
00328 WMitem<T>& WMitem<T>::operator*= (const T &val) {
00329   return operator=(get_value()*val);
00330 }
00331 
00332 template<class T>
00333 WMitem<T>& WMitem<T>::operator/= (const T &val) {
00334   return operator=(get_value()/val);
00335 }
00336 
00337 //================================================================
00338 //
00339 // Three versions of lookup_WMentry with different argument types,
00340 // and one version of create_WMentry, which they share.  
00341 //
00342 // The lookup_reg function is defined in WMclass.c since it's not
00343 // templated.
00344 
00345 template<typename T>
00346 WMitem<T> lookup_WMentry(const std::string &iname,
00347                          const std::string &tname,
00348                          const std::string &regname) {
00349   WMregistry* reg = 0;
00350   for (std::vector<WMentry*>::const_iterator it = GlobalWM.entries.begin(); it != GlobalWM.entries.end(); it++) {
00351     if ( (*it)->item_name == regname ) {
00352       reg = static_cast<WMregistry*>((*it)->item->value);
00353       break;
00354     };
00355   };
00356   if ( reg == 0 ) {
00357     reg = new WMregistry(regname, &GlobalWM);
00358     create_WMentry(regname, "WMregistry", reg, GlobalWM);
00359   };
00360   return lookup_WMentry<T>(iname, tname, *reg);
00361 }
00362 
00363 template<typename T>
00364 WMitem<T> lookup_WMentry(const std::string &iname,
00365                          const std::string &tname, 
00366                          WMregistry &reg) {
00367   for (std::vector<WMentry*>::const_iterator it = reg.entries.begin(); it != reg.entries.end(); it++) {
00368     if ( (*it)->item_name == iname )
00369       return *static_cast<WMitem<T> const*>((*it)->item);
00370   };
00371   return create_WMentry(iname, tname, new T, reg);
00372 }
00373 
00374 template<typename T>
00375 WMitem<T> lookup_WMentry(const std::string &iname,
00376                          const std::string &tname,
00377                          T const &initval, WMregistry &reg) {
00378   for (std::vector<WMentry*>::const_iterator it = reg.entries.begin(); it != reg.entries.end(); it++) {
00379     if ( (*it)->item_name == iname )
00380       return *static_cast<WMitem<T> const*>((*it)->item);
00381   };
00382   return create_WMentry(iname, tname, new T(initval), reg);
00383 }
00384  
00385 template<typename T>
00386 WMitem<T> create_WMentry(const std::string &iname, 
00387                          const std::string &tname, 
00388                          T* const value, WMregistry &reg) {
00389   WMentry* new_entry = new WMentry(iname, tname, new WMitem<T>(value), &reg);
00390   new_entry->item->entry = new_entry;
00391   reg.entries.push_back(new_entry);
00392   return *static_cast<WMitem<T> const*>(new_entry->item);
00393 }
00394 
00395 #endif
00396 

Tekkotsu v4.0
Generated Thu Nov 22 00:54:57 2007 by Doxygen 1.5.4