1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 * Steve Reinhardt 30 */ 31 32#include <sys/time.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <errno.h> 36 37#include <fstream> 38#include <list> 39#include <string> 40#include <vector> 41 42#include "base/inifile.hh" 43#include "base/misc.hh" 44#include "base/output.hh" 45#include "base/str.hh" 46#include "base/trace.hh"
| 1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 * Steve Reinhardt 30 */ 31 32#include <sys/time.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <errno.h> 36 37#include <fstream> 38#include <list> 39#include <string> 40#include <vector> 41 42#include "base/inifile.hh" 43#include "base/misc.hh" 44#include "base/output.hh" 45#include "base/str.hh" 46#include "base/trace.hh"
|
48#include "sim/eventq.hh" 49#include "sim/param.hh" 50#include "sim/serialize.hh" 51#include "sim/sim_events.hh" 52#include "sim/sim_exit.hh" 53#include "sim/sim_object.hh" 54 55using namespace std; 56 57int Serializable::ckptMaxCount = 0; 58int Serializable::ckptCount = 0; 59int Serializable::ckptPrevCount = -1; 60 61void 62Serializable::nameOut(ostream &os) 63{ 64 os << "\n[" << name() << "]\n"; 65} 66 67void 68Serializable::nameOut(ostream &os, const string &_name) 69{ 70 os << "\n[" << _name << "]\n"; 71} 72 73template <class T> 74void 75paramOut(ostream &os, const std::string &name, const T ¶m) 76{ 77 os << name << "="; 78 showParam(os, param); 79 os << "\n"; 80} 81 82 83template <class T> 84void 85paramIn(Checkpoint *cp, const std::string §ion, 86 const std::string &name, T ¶m) 87{ 88 std::string str; 89 if (!cp->find(section, name, str) || !parseParam(str, param)) { 90 fatal("Can't unserialize '%s:%s'\n", section, name); 91 } 92} 93 94 95template <class T> 96void 97arrayParamOut(ostream &os, const std::string &name, 98 const T *param, int size) 99{ 100 os << name << "="; 101 if (size > 0) 102 showParam(os, param[0]); 103 for (int i = 1; i < size; ++i) { 104 os << " "; 105 showParam(os, param[i]); 106 } 107 os << "\n"; 108} 109 110 111template <class T> 112void 113arrayParamIn(Checkpoint *cp, const std::string §ion, 114 const std::string &name, T *param, int size) 115{ 116 std::string str; 117 if (!cp->find(section, name, str)) { 118 fatal("Can't unserialize '%s:%s'\n", section, name); 119 } 120 121 // code below stolen from VectorParam<T>::parse(). 122 // it would be nice to unify these somehow... 123 124 vector<string> tokens; 125 126 tokenize(tokens, str, ' '); 127 128 // Need this if we were doing a vector 129 // value.resize(tokens.size()); 130 131 if (tokens.size() != size) { 132 fatal("Array size mismatch on %s:%s'\n", section, name); 133 } 134 135 for (int i = 0; i < tokens.size(); i++) { 136 // need to parse into local variable to handle vector<bool>, 137 // for which operator[] returns a special reference class 138 // that's not the same as 'bool&', (since it's a packed 139 // vector) 140 T scalar_value; 141 if (!parseParam(tokens[i], scalar_value)) { 142 string err("could not parse \""); 143 144 err += str; 145 err += "\""; 146 147 fatal(err); 148 } 149 150 // assign parsed value to vector 151 param[i] = scalar_value; 152 } 153} 154 155 156void 157objParamIn(Checkpoint *cp, const std::string §ion, 158 const std::string &name, Serializable * ¶m) 159{ 160 if (!cp->findObj(section, name, param)) { 161 fatal("Can't unserialize '%s:%s'\n", section, name); 162 } 163} 164 165 166#define INSTANTIATE_PARAM_TEMPLATES(type) \ 167template void \ 168paramOut(ostream &os, const std::string &name, type const ¶m); \ 169template void \ 170paramIn(Checkpoint *cp, const std::string §ion, \ 171 const std::string &name, type & param); \ 172template void \ 173arrayParamOut(ostream &os, const std::string &name, \ 174 type const *param, int size); \ 175template void \ 176arrayParamIn(Checkpoint *cp, const std::string §ion, \ 177 const std::string &name, type *param, int size); 178 179INSTANTIATE_PARAM_TEMPLATES(signed char) 180INSTANTIATE_PARAM_TEMPLATES(unsigned char) 181INSTANTIATE_PARAM_TEMPLATES(signed short) 182INSTANTIATE_PARAM_TEMPLATES(unsigned short) 183INSTANTIATE_PARAM_TEMPLATES(signed int) 184INSTANTIATE_PARAM_TEMPLATES(unsigned int) 185INSTANTIATE_PARAM_TEMPLATES(signed long) 186INSTANTIATE_PARAM_TEMPLATES(unsigned long) 187INSTANTIATE_PARAM_TEMPLATES(signed long long) 188INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 189INSTANTIATE_PARAM_TEMPLATES(bool) 190INSTANTIATE_PARAM_TEMPLATES(string) 191 192 193///////////////////////////// 194 195/// Container for serializing global variables (not associated with 196/// any serialized object). 197class Globals : public Serializable 198{ 199 public: 200 const string name() const; 201 void serialize(ostream &os); 202 void unserialize(Checkpoint *cp); 203}; 204 205/// The one and only instance of the Globals class. 206Globals globals; 207 208const string 209Globals::name() const 210{ 211 return "Globals"; 212} 213 214void 215Globals::serialize(ostream &os) 216{ 217 nameOut(os); 218 SERIALIZE_SCALAR(curTick); 219 220 nameOut(os, "MainEventQueue"); 221 mainEventQueue.serialize(os); 222} 223 224void 225Globals::unserialize(Checkpoint *cp) 226{ 227 const string §ion = name(); 228 UNSERIALIZE_SCALAR(curTick); 229 230 mainEventQueue.unserialize(cp, "MainEventQueue"); 231} 232 233void 234Serializable::serializeAll() 235{ 236 string dir = Checkpoint::dir(); 237 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 238 fatal("couldn't mkdir %s\n", dir); 239 240 string cpt_file = dir + Checkpoint::baseFilename; 241 ofstream outstream(cpt_file.c_str()); 242 time_t t = time(NULL); 243 outstream << "// checkpoint generated: " << ctime(&t); 244 245 globals.serialize(outstream); 246 SimObject::serializeAll(outstream); 247 248 assert(Serializable::ckptPrevCount + 1 == Serializable::ckptCount); 249 Serializable::ckptPrevCount++; 250 if (ckptMaxCount && ++ckptCount >= ckptMaxCount) 251 exitSimLoop(curTick + 1, "Maximum number of checkpoints dropped"); 252 253} 254 255 256void 257Serializable::unserializeGlobals(Checkpoint *cp) 258{ 259 globals.unserialize(cp); 260} 261 262 263class SerializeEvent : public Event 264{ 265 protected: 266 Tick repeat; 267 268 public: 269 SerializeEvent(Tick _when, Tick _repeat); 270 virtual void process(); 271 virtual void serialize(std::ostream &os) 272 { 273 panic("Cannot serialize the SerializeEvent"); 274 } 275 276}; 277 278SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 279 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 280{ 281 setFlags(AutoDelete); 282 schedule(_when); 283} 284 285void 286SerializeEvent::process() 287{ 288 Serializable::serializeAll(); 289 if (repeat) 290 schedule(curTick + repeat); 291} 292 293const char *Checkpoint::baseFilename = "m5.cpt"; 294 295static string checkpointDirBase; 296 297string 298Checkpoint::dir() 299{ 300 // use csprintf to insert curTick into directory name if it 301 // appears to have a format placeholder in it. 302 return (checkpointDirBase.find("%") != string::npos) ? 303 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 304} 305 306void 307Checkpoint::setup(Tick when, Tick period) 308{ 309 new SerializeEvent(when, period); 310} 311 312class SerializeParamContext : public ParamContext 313{ 314 private: 315 SerializeEvent *event; 316 317 public: 318 SerializeParamContext(const string §ion); 319 ~SerializeParamContext(); 320 void checkParams(); 321}; 322 323SerializeParamContext serialParams("serialize"); 324 325Param<string> serialize_dir(&serialParams, "dir", 326 "dir to stick checkpoint in " 327 "(sprintf format with cycle #)"); 328 329Param<Counter> serialize_cycle(&serialParams, 330 "cycle", 331 "cycle to serialize", 332 0); 333 334Param<Counter> serialize_period(&serialParams, 335 "period", 336 "period to repeat serializations", 337 0); 338 339Param<int> serialize_count(&serialParams, "count", 340 "maximum number of checkpoints to drop"); 341 342SerializeParamContext::SerializeParamContext(const string §ion) 343 : ParamContext(section), event(NULL) 344{ } 345 346SerializeParamContext::~SerializeParamContext() 347{ 348} 349 350void 351SerializeParamContext::checkParams() 352{ 353 checkpointDirBase = simout.resolve(serialize_dir); 354 355 // guarantee that directory ends with a '/' 356 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 357 checkpointDirBase += "/"; 358 359 if (serialize_cycle > 0) 360 Checkpoint::setup(serialize_cycle, serialize_period); 361 362 Serializable::ckptMaxCount = serialize_count; 363} 364 365void 366debug_serialize() 367{ 368 Serializable::serializeAll(); 369} 370 371void 372debug_serialize(Tick when) 373{ 374 new SerializeEvent(when, 0); 375} 376 377//////////////////////////////////////////////////////////////////////// 378// 379// SerializableClass member definitions 380// 381//////////////////////////////////////////////////////////////////////// 382 383// Map of class names to SerializableBuilder creation functions. 384// Need to make this a pointer so we can force initialization on the 385// first reference; otherwise, some SerializableClass constructors 386// may be invoked before the classMap constructor. 387map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 388 389// SerializableClass constructor: add mapping to classMap 390SerializableClass::SerializableClass(const string &className, 391 CreateFunc createFunc) 392{ 393 if (classMap == NULL) 394 classMap = new map<string,SerializableClass::CreateFunc>(); 395 396 if ((*classMap)[className]) 397 { 398 cerr << "Error: simulation object class " << className << " redefined" 399 << endl; 400 fatal(""); 401 } 402 403 // add className --> createFunc to class map 404 (*classMap)[className] = createFunc; 405} 406 407 408// 409// 410Serializable * 411SerializableClass::createObject(Checkpoint *cp, 412 const std::string §ion) 413{ 414 string className; 415 416 if (!cp->find(section, "type", className)) { 417 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 418 section); 419 } 420 421 CreateFunc createFunc = (*classMap)[className]; 422 423 if (createFunc == NULL) { 424 fatal("Serializable::create: no create function for class '%s'.\n", 425 className); 426 } 427 428 Serializable *object = createFunc(cp, section); 429 430 assert(object != NULL); 431 432 return object; 433} 434 435 436Serializable * 437Serializable::create(Checkpoint *cp, const std::string §ion) 438{ 439 Serializable *object = SerializableClass::createObject(cp, section); 440 object->unserialize(cp, section); 441 return object; 442} 443 444
| 47#include "sim/eventq.hh" 48#include "sim/param.hh" 49#include "sim/serialize.hh" 50#include "sim/sim_events.hh" 51#include "sim/sim_exit.hh" 52#include "sim/sim_object.hh" 53 54using namespace std; 55 56int Serializable::ckptMaxCount = 0; 57int Serializable::ckptCount = 0; 58int Serializable::ckptPrevCount = -1; 59 60void 61Serializable::nameOut(ostream &os) 62{ 63 os << "\n[" << name() << "]\n"; 64} 65 66void 67Serializable::nameOut(ostream &os, const string &_name) 68{ 69 os << "\n[" << _name << "]\n"; 70} 71 72template <class T> 73void 74paramOut(ostream &os, const std::string &name, const T ¶m) 75{ 76 os << name << "="; 77 showParam(os, param); 78 os << "\n"; 79} 80 81 82template <class T> 83void 84paramIn(Checkpoint *cp, const std::string §ion, 85 const std::string &name, T ¶m) 86{ 87 std::string str; 88 if (!cp->find(section, name, str) || !parseParam(str, param)) { 89 fatal("Can't unserialize '%s:%s'\n", section, name); 90 } 91} 92 93 94template <class T> 95void 96arrayParamOut(ostream &os, const std::string &name, 97 const T *param, int size) 98{ 99 os << name << "="; 100 if (size > 0) 101 showParam(os, param[0]); 102 for (int i = 1; i < size; ++i) { 103 os << " "; 104 showParam(os, param[i]); 105 } 106 os << "\n"; 107} 108 109 110template <class T> 111void 112arrayParamIn(Checkpoint *cp, const std::string §ion, 113 const std::string &name, T *param, int size) 114{ 115 std::string str; 116 if (!cp->find(section, name, str)) { 117 fatal("Can't unserialize '%s:%s'\n", section, name); 118 } 119 120 // code below stolen from VectorParam<T>::parse(). 121 // it would be nice to unify these somehow... 122 123 vector<string> tokens; 124 125 tokenize(tokens, str, ' '); 126 127 // Need this if we were doing a vector 128 // value.resize(tokens.size()); 129 130 if (tokens.size() != size) { 131 fatal("Array size mismatch on %s:%s'\n", section, name); 132 } 133 134 for (int i = 0; i < tokens.size(); i++) { 135 // need to parse into local variable to handle vector<bool>, 136 // for which operator[] returns a special reference class 137 // that's not the same as 'bool&', (since it's a packed 138 // vector) 139 T scalar_value; 140 if (!parseParam(tokens[i], scalar_value)) { 141 string err("could not parse \""); 142 143 err += str; 144 err += "\""; 145 146 fatal(err); 147 } 148 149 // assign parsed value to vector 150 param[i] = scalar_value; 151 } 152} 153 154 155void 156objParamIn(Checkpoint *cp, const std::string §ion, 157 const std::string &name, Serializable * ¶m) 158{ 159 if (!cp->findObj(section, name, param)) { 160 fatal("Can't unserialize '%s:%s'\n", section, name); 161 } 162} 163 164 165#define INSTANTIATE_PARAM_TEMPLATES(type) \ 166template void \ 167paramOut(ostream &os, const std::string &name, type const ¶m); \ 168template void \ 169paramIn(Checkpoint *cp, const std::string §ion, \ 170 const std::string &name, type & param); \ 171template void \ 172arrayParamOut(ostream &os, const std::string &name, \ 173 type const *param, int size); \ 174template void \ 175arrayParamIn(Checkpoint *cp, const std::string §ion, \ 176 const std::string &name, type *param, int size); 177 178INSTANTIATE_PARAM_TEMPLATES(signed char) 179INSTANTIATE_PARAM_TEMPLATES(unsigned char) 180INSTANTIATE_PARAM_TEMPLATES(signed short) 181INSTANTIATE_PARAM_TEMPLATES(unsigned short) 182INSTANTIATE_PARAM_TEMPLATES(signed int) 183INSTANTIATE_PARAM_TEMPLATES(unsigned int) 184INSTANTIATE_PARAM_TEMPLATES(signed long) 185INSTANTIATE_PARAM_TEMPLATES(unsigned long) 186INSTANTIATE_PARAM_TEMPLATES(signed long long) 187INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 188INSTANTIATE_PARAM_TEMPLATES(bool) 189INSTANTIATE_PARAM_TEMPLATES(string) 190 191 192///////////////////////////// 193 194/// Container for serializing global variables (not associated with 195/// any serialized object). 196class Globals : public Serializable 197{ 198 public: 199 const string name() const; 200 void serialize(ostream &os); 201 void unserialize(Checkpoint *cp); 202}; 203 204/// The one and only instance of the Globals class. 205Globals globals; 206 207const string 208Globals::name() const 209{ 210 return "Globals"; 211} 212 213void 214Globals::serialize(ostream &os) 215{ 216 nameOut(os); 217 SERIALIZE_SCALAR(curTick); 218 219 nameOut(os, "MainEventQueue"); 220 mainEventQueue.serialize(os); 221} 222 223void 224Globals::unserialize(Checkpoint *cp) 225{ 226 const string §ion = name(); 227 UNSERIALIZE_SCALAR(curTick); 228 229 mainEventQueue.unserialize(cp, "MainEventQueue"); 230} 231 232void 233Serializable::serializeAll() 234{ 235 string dir = Checkpoint::dir(); 236 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 237 fatal("couldn't mkdir %s\n", dir); 238 239 string cpt_file = dir + Checkpoint::baseFilename; 240 ofstream outstream(cpt_file.c_str()); 241 time_t t = time(NULL); 242 outstream << "// checkpoint generated: " << ctime(&t); 243 244 globals.serialize(outstream); 245 SimObject::serializeAll(outstream); 246 247 assert(Serializable::ckptPrevCount + 1 == Serializable::ckptCount); 248 Serializable::ckptPrevCount++; 249 if (ckptMaxCount && ++ckptCount >= ckptMaxCount) 250 exitSimLoop(curTick + 1, "Maximum number of checkpoints dropped"); 251 252} 253 254 255void 256Serializable::unserializeGlobals(Checkpoint *cp) 257{ 258 globals.unserialize(cp); 259} 260 261 262class SerializeEvent : public Event 263{ 264 protected: 265 Tick repeat; 266 267 public: 268 SerializeEvent(Tick _when, Tick _repeat); 269 virtual void process(); 270 virtual void serialize(std::ostream &os) 271 { 272 panic("Cannot serialize the SerializeEvent"); 273 } 274 275}; 276 277SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 278 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 279{ 280 setFlags(AutoDelete); 281 schedule(_when); 282} 283 284void 285SerializeEvent::process() 286{ 287 Serializable::serializeAll(); 288 if (repeat) 289 schedule(curTick + repeat); 290} 291 292const char *Checkpoint::baseFilename = "m5.cpt"; 293 294static string checkpointDirBase; 295 296string 297Checkpoint::dir() 298{ 299 // use csprintf to insert curTick into directory name if it 300 // appears to have a format placeholder in it. 301 return (checkpointDirBase.find("%") != string::npos) ? 302 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 303} 304 305void 306Checkpoint::setup(Tick when, Tick period) 307{ 308 new SerializeEvent(when, period); 309} 310 311class SerializeParamContext : public ParamContext 312{ 313 private: 314 SerializeEvent *event; 315 316 public: 317 SerializeParamContext(const string §ion); 318 ~SerializeParamContext(); 319 void checkParams(); 320}; 321 322SerializeParamContext serialParams("serialize"); 323 324Param<string> serialize_dir(&serialParams, "dir", 325 "dir to stick checkpoint in " 326 "(sprintf format with cycle #)"); 327 328Param<Counter> serialize_cycle(&serialParams, 329 "cycle", 330 "cycle to serialize", 331 0); 332 333Param<Counter> serialize_period(&serialParams, 334 "period", 335 "period to repeat serializations", 336 0); 337 338Param<int> serialize_count(&serialParams, "count", 339 "maximum number of checkpoints to drop"); 340 341SerializeParamContext::SerializeParamContext(const string §ion) 342 : ParamContext(section), event(NULL) 343{ } 344 345SerializeParamContext::~SerializeParamContext() 346{ 347} 348 349void 350SerializeParamContext::checkParams() 351{ 352 checkpointDirBase = simout.resolve(serialize_dir); 353 354 // guarantee that directory ends with a '/' 355 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 356 checkpointDirBase += "/"; 357 358 if (serialize_cycle > 0) 359 Checkpoint::setup(serialize_cycle, serialize_period); 360 361 Serializable::ckptMaxCount = serialize_count; 362} 363 364void 365debug_serialize() 366{ 367 Serializable::serializeAll(); 368} 369 370void 371debug_serialize(Tick when) 372{ 373 new SerializeEvent(when, 0); 374} 375 376//////////////////////////////////////////////////////////////////////// 377// 378// SerializableClass member definitions 379// 380//////////////////////////////////////////////////////////////////////// 381 382// Map of class names to SerializableBuilder creation functions. 383// Need to make this a pointer so we can force initialization on the 384// first reference; otherwise, some SerializableClass constructors 385// may be invoked before the classMap constructor. 386map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 387 388// SerializableClass constructor: add mapping to classMap 389SerializableClass::SerializableClass(const string &className, 390 CreateFunc createFunc) 391{ 392 if (classMap == NULL) 393 classMap = new map<string,SerializableClass::CreateFunc>(); 394 395 if ((*classMap)[className]) 396 { 397 cerr << "Error: simulation object class " << className << " redefined" 398 << endl; 399 fatal(""); 400 } 401 402 // add className --> createFunc to class map 403 (*classMap)[className] = createFunc; 404} 405 406 407// 408// 409Serializable * 410SerializableClass::createObject(Checkpoint *cp, 411 const std::string §ion) 412{ 413 string className; 414 415 if (!cp->find(section, "type", className)) { 416 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 417 section); 418 } 419 420 CreateFunc createFunc = (*classMap)[className]; 421 422 if (createFunc == NULL) { 423 fatal("Serializable::create: no create function for class '%s'.\n", 424 className); 425 } 426 427 Serializable *object = createFunc(cp, section); 428 429 assert(object != NULL); 430 431 return object; 432} 433 434 435Serializable * 436Serializable::create(Checkpoint *cp, const std::string §ion) 437{ 438 Serializable *object = SerializableClass::createObject(cp, section); 439 object->unserialize(cp, section); 440 return object; 441} 442 443
|