Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_STAGE_H_ 00002 #define SimTK_SimTKCOMMON_STAGE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 #include "SimTKcommon/internal/common.h" 00028 #include "SimTKcommon/internal/String.h" 00029 #include "SimTKcommon/internal/Exception.h" 00030 00031 #include <cassert> 00032 #include <iostream> 00033 #include <iomanip> 00034 #include <cstdarg> 00035 00036 namespace SimTK { 00037 00050 class Stage { 00051 public: 00052 enum Level { 00053 Empty = 0, 00054 Topology = 1, 00055 Model = 2, 00056 Instance = 3, 00057 Time = 4, 00058 Position = 5, 00059 Velocity = 6, 00060 Dynamics = 7, 00061 Acceleration = 8, 00062 Report = 9, 00063 Infinity = 10, 00064 00065 LowestValid = Empty, 00066 HighestValid = Infinity, 00067 LowestRuntime = Model, 00068 HighestRuntime = Report 00069 }; 00070 00071 enum { 00072 NValid = HighestValid-LowestValid+1, 00073 NRuntime = HighestRuntime-LowestRuntime+1 00074 }; 00075 00077 Stage() : level(Stage::Empty) {} 00079 Stage(Level l) { 00080 assert(LowestValid <= l && l <= HighestValid); 00081 level = l; 00082 } 00084 explicit Stage(int l) { 00085 assert(LowestValid <= l && l <= HighestValid); 00086 level = Level(l); 00087 } 00089 operator int() const {return level;} 00090 00091 bool operator==(Level other) const {return level==other;} 00092 bool operator!=(Level other) const {return level!=other;} 00093 bool operator<(Level other) const {return level<other;} 00094 bool operator<=(Level other) const {return level<=other;} 00095 bool operator>(Level other) const {return level>other;} 00096 bool operator>=(Level other) const {return level>=other;} 00097 bool operator==(Stage other) const {return level==other.level;} 00098 bool operator!=(Stage other) const {return level!=other.level;} 00099 bool operator<(Stage other) const {return level<other.level;} 00100 bool operator<=(Stage other) const {return level<=other.level;} 00101 bool operator>(Stage other) const {return level>other.level;} 00102 bool operator>=(Stage other) const {return level>=other.level;} 00103 00104 // Prefix operators 00105 const Stage& operator++() 00106 { assert(level<HighestValid); level=Level(level+1); return *this; } 00107 const Stage& operator--() 00108 { assert(level>LowestValid); level=Level(level-1); return *this;} 00109 // Postfix operators 00110 Stage operator++(int) 00111 { assert(level<HighestValid); level=Level(level+1); return prev(); } 00112 Stage operator--(int) 00113 { assert(level>LowestValid); level=Level(level-1); return next(); } 00114 00118 Stage next() const 00119 { assert(level<HighestValid); return Stage(Level(level+1)); } 00123 Stage prev() const 00124 { assert(level>LowestValid); return Stage(Level(level-1)); } 00125 00128 String getName() const { 00129 switch (level) { 00130 case Empty: return "Empty"; break; 00131 case Topology: return "Topology"; break; 00132 case Model: return "Model"; break; 00133 case Instance: return "Instance"; break; 00134 case Time: return "Time"; break; 00135 case Position: return "Position"; break; 00136 case Velocity: return "Velocity"; break; 00137 case Dynamics: return "Dynamics"; break; 00138 case Acceleration: return "Acceleration"; break; 00139 case Report: return "Report"; break; 00140 case Infinity: return "Infinity"; break; 00141 default: assert(!"Stage::getName(): illegal level"); 00142 } 00143 return String("INVALID STAGE LEVEL ") + String(level); 00144 } 00145 00147 void invalidate(Stage tooHigh) { 00148 if (level >= tooHigh.level) 00149 *this = tooHigh.prev(); 00150 } 00151 00155 bool isInRuntimeRange() const 00156 { return Stage::LowestRuntime <= level 00157 && level <= Stage::HighestRuntime; } 00158 00159 private: 00160 Level level; 00161 }; 00162 00163 00164 00165 00166 namespace Exception { 00167 00168 class RealizeTopologyMustBeCalledFirst : public Base { 00169 public: 00170 RealizeTopologyMustBeCalledFirst(const char* fn, int ln, 00171 const char* objectType, // e.g., "System", "Subsystem" 00172 const char* objectName, const char* methodName) : Base(fn,ln) 00173 { 00174 setMessage(String(methodName) + ": " + String(objectType) + " " + String(objectName) 00175 + " topology has not been realized since the last topological change" 00176 " -- you must call realizeTopology() first."); 00177 } 00178 virtual ~RealizeTopologyMustBeCalledFirst() throw() { } 00179 }; 00180 00181 class StateAndSystemTopologyVersionsMustMatch : public Base { 00182 public: 00183 StateAndSystemTopologyVersionsMustMatch(const char* fn, int ln, 00184 const char* objectType, // e.g., "System", "Subsystem" 00185 const char* objectName, const char* methodName, 00186 int sysTopoVersion, 00187 int stateTopoVersion) : Base(fn,ln) 00188 { 00189 setMessage(String(methodName) 00190 + ": The given State's Topology stage version number (" 00191 + String(stateTopoVersion) 00192 + ") doesn't match the current topology cache version number (" 00193 + String(sysTopoVersion) 00194 + ") of " + String(objectType) + " " + String(objectName) + "." 00195 + " That means there has been a topology change to this System since this" 00196 " State was created so they are no longer compatible. You should create" 00197 " a new State from the System's default State." 00198 " (Loopholes exist for advanced users.)"); 00199 } 00200 virtual ~StateAndSystemTopologyVersionsMustMatch() throw() { } 00201 }; 00202 00203 00204 00205 class StageTooLow : public Base { 00206 public: 00207 StageTooLow(const char* fn, int ln, 00208 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00209 { 00210 setMessage("Expected stage to be at least " + targetStage.getName() + " in " + String(where) 00211 + " but current stage was " + currentStage.getName()); 00212 } 00213 virtual ~StageTooLow() throw() { } 00214 }; 00215 00216 class StageIsWrong : public Base { 00217 public: 00218 StageIsWrong(const char* fn, int ln, 00219 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00220 { 00221 setMessage("Expected stage to be " + targetStage.getName() + " in " + String(where) 00222 + " but current stage was " + currentStage.getName()); 00223 } 00224 virtual ~StageIsWrong() throw() { } 00225 }; 00226 00227 class StageTooHigh : public Base { 00228 public: 00229 StageTooHigh(const char* fn, int ln, 00230 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00231 { 00232 setMessage("Expected stage to be less than " + targetStage.getName() + " in " + String(where) 00233 + " but current stage was " + currentStage.getName()); 00234 } 00235 virtual ~StageTooHigh() throw() { } 00236 }; 00237 00238 class StageOutOfRange : public Base { 00239 public: 00240 StageOutOfRange(const char* fn, int ln, 00241 Stage lower, Stage currentStage, Stage upper, const char* where) : Base(fn,ln) 00242 { 00243 setMessage("Expected (" + lower.getName() + " <= stage <= " + upper.getName() + ") in " + String(where) 00244 + " but stage was " + currentStage.getName()); 00245 } 00246 virtual ~StageOutOfRange() throw() { } 00247 }; 00248 00249 class CacheEntryOutOfDate : public Base { 00250 public: 00251 CacheEntryOutOfDate(const char* fn, int ln, 00252 Stage currentStage, Stage dependsOn, int dependsOnVersion, int lastCalculatedVersion) 00253 : Base(fn,ln) 00254 { 00255 setMessage("State Cache entry was out of date at Stage " + currentStage.getName() 00256 + ". This entry depends on version " + String(dependsOnVersion) 00257 + " of Stage " + dependsOn.getName() 00258 + " but was last updated at version " + String(lastCalculatedVersion) + "."); 00259 } 00260 virtual ~CacheEntryOutOfDate() throw() { } 00261 }; 00262 00263 // An attempt to realize a particular subsystem to a particular stage failed. 00264 class RealizeCheckFailed : public Base { 00265 public: 00266 RealizeCheckFailed(const char* fn, int ln, Stage g, 00267 int subsystemId, const char* subsystemName, 00268 const char* fmt ...) : Base(fn,ln) 00269 { 00270 char buf[1024]; 00271 va_list args; 00272 va_start(args, fmt); 00273 vsprintf(buf, fmt, args); 00274 setMessage("Couldn't realize subsystem " + String(subsystemId) 00275 + "(" + String(subsystemName) + ") to Stage " 00276 + g.getName() + ": " + String(buf) + "."); 00277 va_end(args); 00278 } 00279 virtual ~RealizeCheckFailed() throw() { } 00280 }; 00281 00282 00283 } // namespace Exception 00284 00285 inline std::ostream& operator<<(std::ostream& o, Stage g) 00286 { o << g.getName(); return o; } 00287 00288 00289 } // namespace SimTK 00290 00291 // REALIZECHECKs: these should be used to catch and report problems that 00292 // occur when realizing a subsystem. 00293 00294 #define SimTK_REALIZECHECK_ALWAYS(cond,stage,subsysIx,subsysName,msg) \ 00295 do{if(!(cond))SimTK_THROW4(SimTK::Exception::RealizeCheckFailed, \ 00296 (stage),(subsysIx),(subsysName),(msg)); \ 00297 }while(false) 00298 #define SimTK_REALIZECHECK1_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1) \ 00299 do{if(!(cond))SimTK_THROW5(SimTK::Exception::RealizeCheckFailed, \ 00300 (stage),(subsysIx),(subsysName),(msg),(a1)); \ 00301 }while(false) 00302 #define SimTK_REALIZECHECK2_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2)\ 00303 do{if(!(cond))SimTK_THROW6(SimTK::Exception::RealizeCheckFailed, \ 00304 (stage),(subsysIx),(subsysName),(msg),(a1),(a2)); \ 00305 }while(false) 00306 #define SimTK_REALIZECHECK3_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3) \ 00307 do{if(!(cond))SimTK_THROW7(SimTK::Exception::RealizeCheckFailed, \ 00308 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3)); \ 00309 }while(false) 00310 #define SimTK_REALIZECHECK4_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3,a4) \ 00311 do{if(!(cond))SimTK_THROW8(SimTK::Exception::RealizeCheckFailed, \ 00312 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3),(a4)); \ 00313 }while(false) 00314 #define SimTK_REALIZECHECK5_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3,a4,a5) \ 00315 do{if(!(cond))SimTK_THROW9(SimTK::Exception::RealizeCheckFailed, \ 00316 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3),(a4),(a5)); \ 00317 }while(false) 00318 00319 00320 #endif // SimTK_SimTKCOMMON_STAGE_H_