Simbody  3.4 (development)
Stage.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines