Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

Monitor.h

Go to the documentation of this file.
00001 #ifndef MONITOR_H 00002 #define MONITOR_H 00003 00004 #include <PtMutex.h> 00005 #include <LockHolder.h> 00006 #include <PtCondition.h> 00007 00008 /* 00009 Bundles together everything you need for a monitor variable. 00010 00011 Note on setting values: 00012 There are two different, valid ways to change the Monitor's value. They are: 00013 00014 (A) Call setValue(...), or 00015 00016 (B) Have code like this: 00017 Monitor m(...); 00018 ... 00019 { 00020 LockHolder lh(m); 00021 ... 00022 (do modifying operations on m._value) 00023 ... 00024 m._cond.broadcast(); 00025 } 00026 00027 Remember, though, that the idea of this Monitor is that any state change should 00028 be theoretically apparent using == or != comparisons. This class is not intended 00029 to just be a general mutex-protector of any old interesting class. It's meant to 00030 be a low-level primitive to wrap things like strings, ints, sets, etc. 00031 */ 00032 template<typename T> 00033 class Monitor 00034 { 00035 public: 00036 Monitor(const T & initialValue) 00037 throw (exception); 00038 00039 Monitor() 00040 throw (exception); 00041 00042 virtual ~Monitor() 00043 throw (exception); 00044 00045 // These provide the raw building blocks from which a Monitor is built... 00046 PtMutex _mtx; 00047 PtCondition _cond; 00048 T _value; 00049 00050 //----------------------------------------------------------------------------- 00051 // The following helper method can be used *in place of* the raw building 00052 // blocks listed above. THE CALLER MUST *NOT* HOLD A LOCK ON _MTX WHEN CALLING 00053 // ANY OF THESE FUNCTIONS... 00054 //----------------------------------------------------------------------------- 00055 00056 void setValue(const T & v) 00057 throw (exception); 00058 00059 // Returns a snapshot of _value's current state. If you don't wany copying to 00060 // occur (as this method must do), you should instead write code that looks 00061 // like the following: 00062 // Monitor m(...); 00063 // ... 00064 // { 00065 // LockHolder lh(m); 00066 // // make extensive, read-only use of m._value 00067 // } 00068 T getValueCopy() 00069 throw (exception); 00070 00071 // Blocks until (_value == v). Uses operator==. 00072 void awaitValueEquals(const T & v) 00073 throw (exception); 00074 00075 // Blocks until (_value != v). Uses operator!=. 00076 void awaitValueNotEquals(const T & v) 00077 throw (exception); 00078 00079 // Like awaitValueNotEquals(...), but also returns the new value. 00080 T getValueWhenNotEquals(const T & v) 00081 throw (exception); 00082 }; 00083 00084 //=============================================================================== 00085 00086 template<typename T> Monitor<T>::Monitor(const T & initialValue) 00087 throw (exception) : 00088 _value(initialValue) 00089 { 00090 } 00091 00092 //=============================================================================== 00093 00094 template<typename T> Monitor<T>::Monitor() 00095 throw (exception) 00096 { 00097 } 00098 00099 //=============================================================================== 00100 00101 template<typename T> Monitor<T>::~Monitor() 00102 throw (exception) 00103 { 00104 } 00105 00106 //=============================================================================== 00107 00108 template<typename T> void Monitor<T>::setValue(const T & v) 00109 throw (exception) 00110 { 00111 LockHolder lh(_mtx); 00112 _value = v; 00113 _cond.broadcast(); 00114 } 00115 00116 //=============================================================================== 00117 00118 template<typename T> T Monitor<T>::getValueCopy() 00119 throw (exception) 00120 { 00121 LockHolder lh(_mtx); 00122 return _value; 00123 } 00124 00125 //=============================================================================== 00126 00127 template<typename T> void Monitor<T>::awaitValueEquals(const T & v) 00128 throw (exception) 00129 { 00130 while (true) 00131 { 00132 LockHolder lh(_mtx); 00133 00134 if (_value == v) 00135 { 00136 return; 00137 } 00138 else 00139 { 00140 _mtx.waitCond(_cond); 00141 } 00142 } 00143 } 00144 00145 //=============================================================================== 00146 00147 template<typename T> void Monitor<T>::awaitValueNotEquals(const T & v) 00148 throw (exception) 00149 { 00150 while (true) 00151 { 00152 LockHolder lh(_mtx); 00153 00154 if (_value != v) 00155 { 00156 return; 00157 } 00158 else 00159 { 00160 _mtx.waitCond(_cond); 00161 } 00162 } 00163 } 00164 00165 //=============================================================================== 00166 00167 template<typename T> T Monitor<T>::getValueWhenNotEquals(const T & v) 00168 throw (exception) 00169 { 00170 while (true) 00171 { 00172 LockHolder lh(_mtx); 00173 00174 if (_value != v) 00175 { 00176 return _value; 00177 } 00178 else 00179 { 00180 _mtx.waitCond(_cond); 00181 } 00182 } 00183 } 00184 00185 00186 //=============================================================================== 00187 00188 #endif

Generated on Fri Nov 12 15:15:21 2004 for Borealis by doxygen 1.3.8