00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef WATCHED_H
00017 #define WATCHED_H
00018
00019 #ifndef USE_PCH
00020 #include <set>
00021 #include <boost/shared_ptr.hpp>
00022 #include "debug.h"
00023 #endif
00024
00025 #include "ExpressionInterface.h"
00026
00027 class ExpressionEventServer;
00028 template<typename T> class Watched;
00029
00030
00031 template<typename T>
00032 class WatchedExpression : public ExpressionInterface {
00033 public:
00034 typedef T const& evaluation_type;
00035
00036 private:
00037 Watched<T>& M_b;
00038
00039 public:
00040
00041 WatchedExpression(Watched<T>& b) : M_b(b) { }
00042
00043
00044 ExpressionEventServer& create_event_server(void);
00045
00046 T const& evaluate_impl(void) const;
00047
00048
00049 void sub_event_server_impl(ExpressionEventServer*);
00050
00051 virtual void add_event_server(boost::shared_ptr<ExpressionEventServer> const& event_server);
00052
00053
00054
00055
00056 virtual bool evaluate(void)
00057 { DoutFatal(dc::core, "Calling WatchedExpression<" << type_info_of<T>().demangled_name() << ">::evaluate()");
00058 return false; }
00059
00060 virtual void sub_event_server(ExpressionEventServer* event_server) { sub_event_server_impl(event_server); }
00061 #ifdef CWDEBUG
00062 virtual void print_on(std::ostream& os) const;
00063 #endif
00064 };
00065
00066
00067
00068
00069
00070
00071
00072
00073 template<typename T>
00074 class Watched {
00075 private:
00076 T M_value;
00077 bool M_being_destructed;
00078 std::set<boost::shared_ptr<ExpressionEventServer> > M_event_servers;
00079 #ifdef CWDEBUG
00080 char const* M_name;
00081 #endif
00082
00083 public:
00084 #ifdef CWDEBUG
00085
00086 explicit Watched(char const* name) : M_being_destructed(false), M_name(name) { }
00087
00088 explicit Watched(char const* name, T const& value) : M_value(value), M_being_destructed(false), M_name(name) { }
00089 #else
00090
00091 Watched(void) : M_being_destructed(false) { }
00092 Watched(T const& value) : M_value(value), M_being_destructed(false) { }
00093 #endif
00094
00095 Watched(Watched const& b) : M_value(b.M_value), M_being_destructed(false)
00096 {
00097 #ifdef CWDEBUG
00098 if (!b.M_event_servers.empty())
00099 Dout(dc::warning, "Copy-constructing a Watched<" <<
00100 type_info_of<T>().demangled_name() << "> that is being used by one or more ExpressionEventServer's");
00101 #endif
00102 }
00103
00104 ~Watched();
00105
00106 #ifdef CWDEBUG
00107
00108 void print_name(std::ostream& os) const { os << M_name; }
00109 #endif
00110
00111
00112 void add_event_server(boost::shared_ptr<ExpressionEventServer> const& event_server)
00113 {
00114 M_event_servers.insert(event_server);
00115 }
00116
00117
00118 void sub_event_server(ExpressionEventServer* event_server)
00119 {
00120 if (M_being_destructed)
00121 return;
00122 std::set<boost::shared_ptr<ExpressionEventServer> >::iterator iter = M_event_servers.begin();
00123 while (iter != M_event_servers.end())
00124 {
00125 if ((*iter).get() == event_server)
00126 break;
00127 ++iter;
00128 }
00129 ASSERT(iter != M_event_servers.end());
00130 M_event_servers.erase(iter);
00131 }
00132
00133
00134 template<typename T2>
00135 Watched& operator=(T2 const& b)
00136 {
00137 T previous_value(M_value);
00138 M_value = b;
00139 if (M_value != previous_value)
00140 changed_to(M_value);
00141 return *this;
00142 }
00143
00144
00145 Watched& operator=(Watched const& b)
00146 {
00147 if (M_value != b.M_value)
00148 changed_to(b.M_value);
00149 return *this;
00150 }
00151
00152
00153 template<typename T2>
00154 Watched& operator&=(T2 const& b)
00155 {
00156 T previous_value(M_value);
00157 M_value &= b;
00158 if (M_value != previous_value)
00159 changed_to(M_value);
00160 return *this;
00161 }
00162
00163
00164 Watched& operator&=(Watched const& b)
00165 {
00166 T previous_value(M_value);
00167 M_value &= b.M_value;
00168 if (M_value != previous_value)
00169 changed_to(M_value);
00170 return *this;
00171 }
00172
00173
00174 template<typename T2>
00175 Watched& operator|=(T2 const& b)
00176 {
00177 T previous_value(M_value);
00178 M_value |= b;
00179 if (M_value != previous_value)
00180 changed_to(M_value);
00181 return *this;
00182 }
00183
00184
00185 Watched& operator|=(Watched const& b)
00186 {
00187 T previous_value(M_value);
00188 M_value |= b.M_value;
00189 if (M_value != previous_value)
00190 changed_to(M_value);
00191 return *this;
00192 }
00193
00194
00195 template<typename T2>
00196 Watched& operator^=(T2 const& b)
00197 {
00198 T previous_value(M_value);
00199 M_value ^= b;
00200 if (M_value != previous_value)
00201 changed_to(M_value);
00202 return *this;
00203 }
00204
00205
00206 Watched& operator^=(Watched const& b)
00207 {
00208 T previous_value(M_value);
00209 M_value ^= b.M_value;
00210 if (M_value != previous_value)
00211 changed_to(M_value);
00212 return *this;
00213 }
00214
00215
00216 T operator~(void) { return ~M_value; }
00217
00218
00219 WatchedExpression<T> operator*(void) { return WatchedExpression<T>(*this); }
00220
00221
00222 T const& value(void) const { return M_value; }
00223
00224
00225 operator T const& () { return M_value; }
00226
00227 template<typename T2>
00228 friend std::ostream& operator<<(std::ostream& os, Watched<T2> const& b);
00229
00230 private:
00231 void changed_to(T const& b);
00232 };
00233
00234
00235 template<typename T>
00236 std::ostream& operator<<(std::ostream& os, Watched<T> const& b)
00237 {
00238 return os << b.M_value;
00239 }
00240
00241
00242 template<typename T1, typename T2> bool operator==(Watched<T1> const& v1, T2 const& v2) { return v1.value() == v2; }
00243
00244 template<typename T1, typename T2> bool operator!=(Watched<T1> const& v1, T2 const& v2) { return v1.value() != v2; }
00245
00246 template<typename T1, typename T2> bool operator<(Watched<T1> const& v1, T2 const& v2) { return v1.value() < v2; }
00247
00248 template<typename T1, typename T2> bool operator<=(Watched<T1> const& v1, T2 const& v2) { return v1.value() <= v2; }
00249
00250 template<typename T1, typename T2> bool operator>(Watched<T1> const& v1, T2 const& v2) { return v1.value() > v2; }
00251
00252 template<typename T1, typename T2> bool operator>=(Watched<T1> const& v1, T2 const& v2) { return v1.value() >= v2; }
00253
00254 template<typename T1, typename T2> T1 operator&(Watched<T1> const& v1, T2 const& v2) { return v1.value() & v2; }
00255
00256 template<typename T1, typename T2> T1 operator|(Watched<T1> const& v1, T2 const& v2) { return v1.value() | v2; }
00257
00258 template<typename T1, typename T2> T1 operator^(Watched<T1> const& v1, T2 const& v2) { return v1.value() ^ v2; }
00259
00260 #ifdef CWDEBUG
00261
00262 template<typename T>
00263 void WatchedExpression<T>::print_on(std::ostream& os) const
00264 {
00265 M_b.print_name(os);
00266 }
00267 #endif
00268
00269
00270 template<typename T>
00271 void WatchedExpression<T>::add_event_server(boost::shared_ptr<ExpressionEventServer> const& event_server)
00272 {
00273 M_b.add_event_server(event_server);
00274 }
00275
00276
00277 template<typename T>
00278 T const& WatchedExpression<T>::evaluate_impl(void) const
00279 {
00280 return M_b.value();
00281 }
00282
00283
00284 template<typename T>
00285 void WatchedExpression<T>::sub_event_server_impl(ExpressionEventServer* event_server)
00286 {
00287 M_b.sub_event_server(event_server);
00288 }
00289
00290 #include "Expression.h"
00291
00292
00293 template<typename T>
00294 void Watched<T>::changed_to(T const& b)
00295 {
00296 M_value = b;
00297 std::set<boost::shared_ptr<ExpressionEventServer> >::iterator iter = M_event_servers.begin();
00298
00299 while (iter != M_event_servers.end())
00300 (*iter++)->bool_changed();
00301 }
00302
00303
00304 template<typename T>
00305 Watched<T>::~Watched()
00306 {
00307 M_being_destructed = true;
00308 for (std::set<boost::shared_ptr<ExpressionEventServer> >::iterator iter = M_event_servers.begin(); iter != M_event_servers.end();)
00309 (*iter++)->bool_destructed();
00310 }
00311
00312 #endif // WATCHED_H
00313