Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_STAGE_H_ 00002 #define SimTK_SimTKCOMMON_STAGE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core 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. * 00011 * * 00012 * Portions copyright (c) 2005-7 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00035 #include "SimTKcommon/internal/common.h" 00036 #include "SimTKcommon/internal/String.h" 00037 #include "SimTKcommon/internal/Exception.h" 00038 #include "SimTKcommon/internal/Enumeration.h" 00039 00040 #include <cassert> 00041 #include <iostream> 00042 #include <iomanip> 00043 #include <cstdarg> 00044 00045 namespace SimTK { 00046 00061 class SimTK_SimTKCOMMON_EXPORT Stage : public Enumeration<Stage> { 00062 public: 00063 enum Num { 00064 EmptyIndex = 0, // Lower than any legitimate Stage. 00065 TopologyIndex = 1, // TODO: Constructed, Finalized? 00066 ModelIndex = 2, // TODO: Instantiated, Resourced, Provisioned, Specialized? 00067 InstanceIndex = 3, // TODO: Instanced, Specified? 00068 TimeIndex = 4, 00069 PositionIndex = 5, // TODO: Positioned? 00070 VelocityIndex = 6, // TODO: Velocity, Speed, Rate? 00071 DynamicsIndex = 7, // forces, dynamic properties & operators available 00072 AccelerationIndex = 8, // TODO: Accelerated? 00073 ReportIndex = 9, // TODO: Output? 00074 InfinityIndex = 10 // Higher than any legitimate Stage. 00075 }; 00076 static const Stage Empty; 00077 static const Stage Topology; 00078 static const Stage Model; 00079 static const Stage Instance; 00080 static const Stage Time; 00081 static const Stage Position; 00082 static const Stage Velocity; 00083 static const Stage Dynamics; 00084 static const Stage Acceleration; 00085 static const Stage Report; 00086 static const Stage Infinity; 00087 00088 static const Stage LowestValid; 00089 static const Stage HighestValid; 00090 static const int NValid = InfinityIndex-EmptyIndex+1; 00091 00092 // LowestRuntime->HighestRuntime cover the post-construction stages only. 00093 static const Stage LowestRuntime; 00094 static const Stage HighestRuntime; 00095 static const int NRuntime = ReportIndex-ModelIndex+1; 00096 00097 Stage next() const { return getValue(getIndex()+1); } 00098 Stage prev() const { return getValue(getIndex()-1); } 00099 00100 // Set stage=min(stage, tooHigh-1). 00101 void invalidate(Stage tooHigh) { 00102 if (getIndex() >= tooHigh.getIndex()) 00103 *this = tooHigh.prev(); 00104 } 00105 00106 bool isInRuntimeRange() const {return Stage::LowestRuntime <= getIndex() && getIndex() <= Stage::HighestRuntime;} 00107 00108 private: 00109 Stage(); 00110 Stage(const Stage& thisElement, int index, const char* name); 00111 static void initValues(); 00112 friend class Enumeration<Stage>; 00113 }; 00114 00115 00116 namespace Exception { 00117 00118 class RealizeTopologyMustBeCalledFirst : public Base { 00119 public: 00120 RealizeTopologyMustBeCalledFirst(const char* fn, int ln, 00121 const char* objectType, // e.g., "System", "Subsystem" 00122 const char* objectName, const char* methodName) : Base(fn,ln) 00123 { 00124 setMessage(String(methodName) + ": " + String(objectType) + " " + String(objectName) 00125 + " topology has not yet been realized -- must call realizeTopology() first"); 00126 } 00127 virtual ~RealizeTopologyMustBeCalledFirst() throw() { } 00128 }; 00129 00130 class StageTooLow : public Base { 00131 public: 00132 StageTooLow(const char* fn, int ln, 00133 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00134 { 00135 setMessage("Expected stage to be at least " + targetStage.getName() + " in " + String(where) 00136 + " but current stage was " + currentStage.getName()); 00137 } 00138 virtual ~StageTooLow() throw() { } 00139 }; 00140 00141 class StageIsWrong : public Base { 00142 public: 00143 StageIsWrong(const char* fn, int ln, 00144 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00145 { 00146 setMessage("Expected stage to be " + targetStage.getName() + " in " + String(where) 00147 + " but current stage was " + currentStage.getName()); 00148 } 00149 virtual ~StageIsWrong() throw() { } 00150 }; 00151 00152 class StageTooHigh : public Base { 00153 public: 00154 StageTooHigh(const char* fn, int ln, 00155 Stage currentStage, Stage targetStage, const char* where) : Base(fn,ln) 00156 { 00157 setMessage("Expected stage to be less than " + targetStage.getName() + " in " + String(where) 00158 + " but current stage was " + currentStage.getName()); 00159 } 00160 virtual ~StageTooHigh() throw() { } 00161 }; 00162 00163 class StageOutOfRange : public Base { 00164 public: 00165 StageOutOfRange(const char* fn, int ln, 00166 Stage lower, Stage currentStage, Stage upper, const char* where) : Base(fn,ln) 00167 { 00168 setMessage("Expected (" + lower.getName() + " <= stage <= " + upper.getName() + ") in " + String(where) 00169 + " but stage was " + currentStage.getName()); 00170 } 00171 virtual ~StageOutOfRange() throw() { } 00172 }; 00173 00174 class CacheEntryOutOfDate : public Base { 00175 public: 00176 CacheEntryOutOfDate(const char* fn, int ln, 00177 Stage currentStage, Stage dependsOn, int dependsOnVersion, int lastCalculatedVersion) 00178 : Base(fn,ln) 00179 { 00180 setMessage("State Cache entry was out of date at Stage " + currentStage.getName() 00181 + ". This entry depends on version " + String(dependsOnVersion) 00182 + " of Stage " + dependsOn.getName() 00183 + " but was last updated at version " + String(lastCalculatedVersion) + "."); 00184 } 00185 virtual ~CacheEntryOutOfDate() throw() { } 00186 }; 00187 00188 // An attempt to realize a particular subsystem to a particular stage failed. 00189 class RealizeCheckFailed : public Base { 00190 public: 00191 RealizeCheckFailed(const char* fn, int ln, Stage g, 00192 int subsystemId, const char* subsystemName, 00193 const char* fmt ...) : Base(fn,ln) 00194 { 00195 char buf[1024]; 00196 va_list args; 00197 va_start(args, fmt); 00198 vsprintf(buf, fmt, args); 00199 setMessage("Couldn't realize subsystem " + String(subsystemId) 00200 + "(" + String(subsystemName) + ") to Stage " 00201 + g.getName() + ": " + String(buf) + "."); 00202 va_end(args); 00203 } 00204 virtual ~RealizeCheckFailed() throw() { } 00205 }; 00206 00207 00208 } // namespace Exception 00209 00210 inline std::ostream& operator<<(std::ostream& o, Stage g) { o << g.getName(); return o; } 00211 00212 00213 } // namespace SimTK 00214 00215 // REALIZECHECKs: these should be used to catch and report problems that 00216 // occur when realizing a subsystem. 00217 00218 #define SimTK_REALIZECHECK_ALWAYS(cond,stage,subsysIx,subsysName,msg) \ 00219 do{if(!(cond))SimTK_THROW4(SimTK::Exception::RealizeCheckFailed, \ 00220 (stage),(subsysIx),(subsysName),(msg)); \ 00221 }while(false) 00222 #define SimTK_REALIZECHECK1_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1) \ 00223 do{if(!(cond))SimTK_THROW5(SimTK::Exception::RealizeCheckFailed, \ 00224 (stage),(subsysIx),(subsysName),(msg),(a1)); \ 00225 }while(false) 00226 #define SimTK_REALIZECHECK2_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2)\ 00227 do{if(!(cond))SimTK_THROW6(SimTK::Exception::RealizeCheckFailed, \ 00228 (stage),(subsysIx),(subsysName),(msg),(a1),(a2)); \ 00229 }while(false) 00230 #define SimTK_REALIZECHECK3_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3) \ 00231 do{if(!(cond))SimTK_THROW7(SimTK::Exception::RealizeCheckFailed, \ 00232 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3)); \ 00233 }while(false) 00234 #define SimTK_REALIZECHECK4_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3,a4) \ 00235 do{if(!(cond))SimTK_THROW8(SimTK::Exception::RealizeCheckFailed, \ 00236 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3),(a4)); \ 00237 }while(false) 00238 #define SimTK_REALIZECHECK5_ALWAYS(cond,stage,subsysIx,subsysName,msg,a1,a2,a3,a4,a5) \ 00239 do{if(!(cond))SimTK_THROW9(SimTK::Exception::RealizeCheckFailed, \ 00240 (stage),(subsysIx),(subsysName),(msg),(a1),(a2),(a3),(a4),(a5)); \ 00241 }while(false) 00242 00243 00244 #endif // SimTK_SimTKCOMMON_STAGE_H_