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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:53 2016 by Doxygen 1.6.3