00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifndef __CK_PUP_H
00055 #define __CK_PUP_H
00056
00057 #include <stdio.h>
00058 #include <type_traits>
00059 #include <utility>
00060
00061 #ifndef __cplusplus
00062 #error "Use pup_c.h for C programs-- pup.h is for C++ programs"
00063 #endif
00064
00065 #ifdef STANDALONE_PUP
00066 #define CmiAbort(x) { printf(x); abort(); }
00067 #else
00068 #ifndef CHARM_H
00069 # include "converse.h"
00070 #endif
00071 extern "C" void CmiAbort(const char *msg);
00072 #endif
00073
00074
00075
00076
00077 typedef struct {int is_only_a_name;} CkMigrateMessage;
00078
00079 namespace PUP {
00080 class er;
00081
00087 struct reconstruct {};
00088 namespace detail {
00089 template <typename T, bool b = std::is_constructible<T, reconstruct>::value>
00090 struct TemporaryObjectHolder { };
00091 template <typename T>
00092 struct TemporaryObjectHolder<T, true>
00093 {
00094 typename std::remove_cv<typename std::remove_reference<T>::type>::type t{reconstruct()};
00095 };
00096 template <typename T>
00097 struct TemporaryObjectHolder<T, false>
00098 {
00099 typename std::remove_cv<typename std::remove_reference<T>::type>::type t{};
00100 };
00101 template <typename T>
00102 void operator|(er &p, TemporaryObjectHolder<T> &t) {
00103 p | t.t;
00104 }
00105 }
00106
00107 #if CMK_LONG_LONG_DEFINED
00108 #define CMK_PUP_LONG_LONG long long
00109 #elif CMK___int64_DEFINED
00110 #define CMK_PUP_LONG_LONG __int64
00111 #endif
00112
00113
00114
00115 typedef enum {
00116
00117 Tchar=0,Tshort, Tint, Tlong, Tlonglong,
00118 Tuchar,Tushort,Tuint,Tulong, Tulonglong,
00119 #if CMK_HAS_INT16
00120 Tint128, Tuint128,
00121 #endif
00122 Tfloat,Tdouble,Tlongdouble,
00123 Tbool,
00124 Tbyte,
00125 Tsync,
00126 Tpointer,
00127 dataType_last
00128 } dataType;
00129
00130
00131 typedef unsigned char myByte;
00132
00133
00134 class er;
00135 class able;
00136
00137
00138 class seekBlock {
00139 enum {maxSections=3};
00140 int secTab[maxSections+1];
00141 int nSec;
00142 int secTabOff;
00143 er &p;
00144 bool hasEnded;
00145 public:
00146
00147 seekBlock(er &Np,int nSections);
00148
00149 ~seekBlock();
00150
00151
00152 void seek(int toSection);
00153
00154 void endBlock(void);
00155
00156
00157
00158 union {
00159 size_t off;
00160 long loff;
00161 const myByte *cptr;
00162 myByte *ptr;
00163 void *vptr;
00164 } data;
00165 };
00166
00167
00168 class er {
00169 private:
00170 er(const er &p);
00171 protected:
00173 enum {IS_USERLEVEL=0x0004,
00174 IS_DELETING =0x0008,
00175 IS_COMMENTS =0x0010,
00176 IS_RESTARTING=0x0020
00177 };
00179 enum {IS_SIZING =0x0100,
00180 IS_PACKING =0x0200,
00181 IS_UNPACKING=0x0400,
00182 TYPE_MASK =0xFF00
00183 };
00184 unsigned int PUP_er_state;
00185 explicit
00186 er(unsigned int inType): PUP_er_state(inType) {}
00187 public:
00188 virtual ~er();
00189
00190
00191 bool isSizing(void) const {return (PUP_er_state&IS_SIZING)!=0?true:false;}
00192 bool isPacking(void) const {return (PUP_er_state&IS_PACKING)!=0?true:false;}
00193 bool isUnpacking(void) const {return (PUP_er_state&IS_UNPACKING)!=0?true:false;}
00194 const char * typeString() const;
00195 unsigned int getStateFlags(void) const {return PUP_er_state;}
00196
00197
00198 void becomeDeleting(void) {PUP_er_state|=IS_DELETING;}
00199 bool isDeleting(void) const {return (PUP_er_state&IS_DELETING)!=0?true:false;}
00200
00201
00202 void becomeUserlevel(void) {PUP_er_state|=IS_USERLEVEL;}
00203 bool isUserlevel(void) const {return (PUP_er_state&IS_USERLEVEL)!=0?true:false;}
00204
00205
00206 void becomeRestarting(void) {PUP_er_state|=IS_RESTARTING;}
00207 bool isRestarting(void) const {return (PUP_er_state&IS_RESTARTING)!=0?true:false;}
00208
00209 bool hasComments(void) const {return (PUP_er_state&IS_COMMENTS)!=0?true:false;}
00210
00211
00212 void operator()(signed char &v) {(*this)(&v,1);}
00213 #if CMK_SIGNEDCHAR_DIFF_CHAR
00214 void operator()(char &v) {(*this)(&v,1);}
00215 #endif
00216 void operator()(short &v) {(*this)(&v,1);}
00217 void operator()(int &v) {(*this)(&v,1);}
00218 void operator()(long &v) {(*this)(&v,1);}
00219 void operator()(unsigned char &v) {(*this)(&v,1);}
00220 void operator()(unsigned short &v) {(*this)(&v,1);}
00221 void operator()(unsigned int &v) {(*this)(&v,1);}
00222 void operator()(unsigned long &v) {(*this)(&v,1);}
00223 void operator()(float &v) {(*this)(&v,1);}
00224 void operator()(double &v) {(*this)(&v,1);}
00225 #if CMK_LONG_DOUBLE_DEFINED
00226 void operator()(long double &v) {(*this)(&v,1);}
00227 #endif
00228 void operator()(bool &v) {(*this)(&v,1);}
00229 #ifdef CMK_PUP_LONG_LONG
00230 void operator()(CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
00231 void operator()(unsigned CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
00232 #endif
00233 #if CMK_HAS_INT16
00234 void operator()(CmiInt16 &v) {(*this)(&v,1);}
00235 void operator()(CmiUInt16 &v) {(*this)(&v,1);}
00236 #endif
00237 void operator()(void* &v,void* sig) {(*this)(&v,1,sig);}
00238
00239
00240
00241 void operator()(signed char *a,size_t nItems)
00242 {bytes((void *)a,nItems,sizeof(signed char),Tchar);}
00243 #if CMK_SIGNEDCHAR_DIFF_CHAR
00244 void operator()(char *a,size_t nItems)
00245 {bytes((void *)a,nItems,sizeof(char),Tchar);}
00246 #endif
00247 void operator()(short *a,size_t nItems)
00248 {bytes((void *)a,nItems,sizeof(short),Tshort);}
00249 void operator()(int *a,size_t nItems)
00250 {bytes((void *)a,nItems,sizeof(int),Tint);}
00251 void operator()(long *a,size_t nItems)
00252 {bytes((void *)a,nItems,sizeof(long),Tlong);}
00253
00254
00255 void operator()(unsigned char *a,size_t nItems)
00256 {bytes((void *)a,nItems,sizeof(unsigned char),Tuchar);}
00257 void operator()(unsigned short *a,size_t nItems)
00258 {bytes((void *)a,nItems,sizeof(unsigned short),Tushort);}
00259 void operator()(unsigned int *a,size_t nItems)
00260 {bytes((void *)a,nItems,sizeof(unsigned int),Tuint);}
00261 void operator()(unsigned long *a,size_t nItems)
00262 {bytes((void *)a,nItems,sizeof(unsigned long),Tulong);}
00263
00264
00265 void operator()(float *a,size_t nItems)
00266 {bytes((void *)a,nItems,sizeof(float),Tfloat);}
00267 void operator()(double *a,size_t nItems)
00268 {bytes((void *)a,nItems,sizeof(double),Tdouble);}
00269
00270 #if CMK_LONG_DOUBLE_DEFINED
00271 void operator()(long double *a,size_t nItems)
00272 {bytes((void *)a,nItems,sizeof(long double),Tlongdouble);}
00273 #endif
00274
00275
00276 void operator()(bool *a,size_t nItems)
00277 {bytes((void *)a,nItems,sizeof(bool),Tbool);}
00278
00279 #ifdef CMK_PUP_LONG_LONG
00280 void operator()(CMK_PUP_LONG_LONG *a,size_t nItems)
00281 {bytes((void *)a,nItems,sizeof(CMK_PUP_LONG_LONG),Tlonglong);}
00282 void operator()(unsigned CMK_PUP_LONG_LONG *a,size_t nItems)
00283 {bytes((void *)a,nItems,sizeof(unsigned CMK_PUP_LONG_LONG),Tulonglong);}
00284 #endif
00285 #if CMK_HAS_INT16
00286 void operator()(CmiInt16 *a,size_t nItems)
00287 {bytes((void *)a,nItems,sizeof(CmiInt16),Tint128);}
00288 void operator()(CmiUInt16 *a,size_t nItems)
00289 {bytes((void *)a,nItems,sizeof(CmiUInt16),Tuint128);}
00290 #endif
00291
00292
00293
00294 void operator()(void **a,size_t nItems,void *pointerSignature) {
00295 (void)pointerSignature;
00296 bytes((void *)a,nItems,sizeof(void *),Tpointer);
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 void operator()(able** a)
00308 {object(a);}
00309
00310 void operator()(able& a);
00311
00313 virtual void comment(const char *message);
00314
00317 virtual void synchronize(unsigned int sync);
00318
00321 inline void syncComment(unsigned int sync,const char *message=0) {
00322 #if CMK_ERROR_CHECKING
00323 if (hasComments()) {
00324 synchronize(sync);
00325 if (message) comment(message);
00326 }
00327 #else
00328
00329 #endif
00330 }
00331
00332
00333
00334 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t) =0;
00335 virtual void object(able** a);
00336
00337 virtual size_t size(void) const { return 0; }
00338
00339
00340 virtual void impl_startSeek(seekBlock &s);
00341 virtual size_t impl_tell(seekBlock &s);
00342 virtual void impl_seek(seekBlock &s,size_t off);
00343 virtual void impl_endSeek(seekBlock &s);
00344
00345
00346
00347 virtual void pupCmiAllocBuf(void **msg) {
00348 (void)msg;
00349 CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");
00350 }
00351
00352
00353
00354 virtual void pupCmiAllocBuf(void **msg, size_t size) {
00355 (void)msg;
00356 (void)size;
00357 CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");
00358 }
00359 };
00360
00371 enum {
00372 sync_builtin=0x70000000,
00373 sync_begin=sync_builtin+0x01000000,
00374 sync_end=sync_builtin+0x02000000,
00375 sync_last_system=sync_builtin+0x09000000,
00376 sync_array_m=0x00100000,
00377 sync_list_m=0x00200000,
00378 sync_object_m=0x00300000,
00379
00380 sync_begin_array=sync_begin+sync_array_m,
00381 sync_begin_list=sync_begin+sync_list_m,
00382 sync_begin_object=sync_begin+sync_object_m,
00383
00384 sync_end_array=sync_end+sync_array_m,
00385 sync_end_list=sync_end+sync_list_m,
00386 sync_end_object=sync_end+sync_object_m,
00387
00388 sync_item=sync_builtin+0x00110000,
00389 sync_index=sync_builtin+0x00120000,
00390
00391 sync_last
00392 };
00393
00394
00395
00396 class sizer : public er {
00397 protected:
00398 size_t nBytes;
00399
00400 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00401 public:
00402
00403 sizer(void):er(IS_SIZING),nBytes(0) {}
00404
00405
00406 size_t size(void) const {return nBytes;}
00407 };
00408
00409 template <class T>
00410 inline size_t size(T &t) {
00411 PUP::sizer p; p|t; return p.size();
00412 }
00413
00414
00415 class mem : public er {
00416 protected:
00417 myByte *origBuf;
00418 myByte *buf;
00419 mem(unsigned int type,myByte *Nbuf):er(type),origBuf(Nbuf),buf(Nbuf) {}
00420 mem(const mem &p);
00421 void operator=(const mem &p);
00422
00423
00424 virtual void impl_startSeek(seekBlock &s);
00425 virtual size_t impl_tell(seekBlock &s);
00426 virtual void impl_seek(seekBlock &s,size_t off);
00427 public:
00428
00429 size_t size(void) const {return buf-origBuf;}
00430
00431 inline char* get_current_pointer() const {
00432 return reinterpret_cast<char*>(buf);
00433 }
00434
00435 inline char* get_orig_pointer() const {
00436 return reinterpret_cast<char*>(origBuf);
00437 }
00438
00439 inline void advance(size_t const offset) {
00440 buf += offset;
00441 }
00442 };
00443
00444
00445 class toMem : public mem {
00446 protected:
00447
00448 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00449 public:
00450
00451 toMem(void *Nbuf):mem(IS_PACKING,(myByte *)Nbuf) {}
00452 };
00453 template <class T>
00454 inline void toMemBuf(T &t,void *buf, size_t len) {
00455 PUP::toMem p(buf);
00456 p|t;
00457 if (p.size()!=len) CmiAbort("Size mismatch during PUP::toMemBuf!\n"
00458 "This means your pup routine doesn't match during sizing and packing");
00459 }
00460
00461
00462 class fromMem : public mem {
00463 protected:
00464
00465 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00466 public:
00467
00468 fromMem(const void *Nbuf):mem(IS_UNPACKING,(myByte *)Nbuf) {}
00469 };
00470 template <class T>
00471 inline void fromMemBuf(T &t,void *buf,size_t len) {
00472 PUP::fromMem p(buf);
00473 p|t;
00474 if (p.size()!=len) CmiAbort("Size mismatch during PUP::fromMemBuf!\n"
00475 "This means your pup routine doesn't match during packing and unpacking");
00476 }
00477
00478
00479 class disk : public er {
00480 protected:
00481 FILE *F;
00482 disk(unsigned int type,FILE *f):er(type),F(f) {}
00483 disk(const disk &p);
00484 void operator=(const disk &p);
00485
00486
00487 virtual void impl_startSeek(seekBlock &s);
00488 virtual size_t impl_tell(seekBlock &s);
00489 virtual void impl_seek(seekBlock &s,size_t off);
00490 };
00491
00492
00493 class toDisk : public disk {
00494 protected:
00495
00496 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00497 bool error;
00498 public:
00499
00500
00501
00502 toDisk(FILE *f):disk(IS_PACKING,f) {error = false;}
00503 bool checkError(){return error;}
00504 };
00505
00506
00507 class fromDisk : public disk {
00508 protected:
00509
00510 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00511 public:
00512
00513
00514
00515 fromDisk(FILE *f):disk(IS_UNPACKING,f) {}
00516 };
00517
00518
00519 class toTextUtil : public er {
00520 private:
00521 char *cur;
00522 int level;
00523 void beginEnv(const char *type,int n=0);
00524 void endEnv(const char *type);
00525 char *beginLine(void);
00526 void endLine(void);
00527 protected:
00528 virtual char *advance(char *cur)=0;
00529 toTextUtil(unsigned int inType,char *buf);
00530 toTextUtil(const toTextUtil &p);
00531 void operator=(const toTextUtil &p);
00532 public:
00533 virtual void comment(const char *message);
00534 virtual void synchronize(unsigned int m);
00535 protected:
00536 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00537 virtual void object(able** a);
00538 };
00539
00540 class sizerText : public toTextUtil {
00541 private:
00542 char line[1000];
00543 size_t charCount;
00544 protected:
00545 virtual char *advance(char *cur);
00546 public:
00547 sizerText(void);
00548 size_t size(void) const {return charCount+1; }
00549 };
00550
00551
00552 class toText : public toTextUtil {
00553 private:
00554 char *buf;
00555 size_t charCount;
00556 protected:
00557 virtual char *advance(char *cur);
00558 public:
00559 toText(char *outStr);
00560 toText(const toText &p);
00561 void operator=(const toText &p);
00562 size_t size(void) const {return charCount+1; }
00563 };
00564
00565 class toTextFile : public er {
00566 protected:
00567 FILE *f;
00568 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00569 public:
00570
00571
00572 toTextFile(FILE *f_) :er(IS_PACKING), f(f_) {}
00573 toTextFile(const toTextFile &p);
00574 void operator=(const toTextFile &p);
00575 virtual void comment(const char *message);
00576 };
00577 class fromTextFile : public er {
00578 protected:
00579 FILE *f;
00580 int readInt(const char *fmt="%d");
00581 unsigned int readUint(const char *fmt="%u");
00582 CMK_TYPEDEF_INT8 readLongInt(const char *fmt="%lld");
00583 double readDouble(void);
00584
00585 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00586 virtual void parseError(const char *what);
00587 public:
00588
00589
00590 fromTextFile(FILE *f_) :er(IS_UNPACKING), f(f_) {}
00591 fromTextFile(const fromTextFile &p);
00592 void operator=(const fromTextFile &p);
00593 virtual void comment(const char *message);
00594 };
00595
00596
00597
00598 class machineInfo {
00599 public:
00600 typedef unsigned char myByte;
00601 myByte magic[4];
00602 myByte version;
00603
00604 myByte intBytes[5];
00605 myByte intFormat;
00606
00607 myByte floatBytes;
00608 myByte doubleBytes;
00609 myByte floatFormat;
00610
00611 myByte boolBytes;
00612 myByte pointerBytes;
00613
00614
00615
00616
00617 bool valid(void) const;
00618
00619 bool needsConversion(void) const;
00620
00621
00622 static const machineInfo ¤t(void);
00623
00624 void pup(er &p) {
00625 myByte padding;
00626
00627 p(magic, 4);
00628 p(version);
00629 if (version == 0) p(intBytes, 4);
00630 else p(intBytes, 5);
00631 p(intFormat);
00632 p(floatBytes); p(doubleBytes); p(floatFormat);
00633 p(boolBytes); p(pointerBytes);
00634 if (version == 0) p(padding);
00635 }
00636 };
00637
00639 class wrap_er : public er {
00640 protected:
00641 er &p;
00642 public:
00643 wrap_er(er &p_,unsigned int newFlags=0) :er(p_.getStateFlags()|newFlags), p(p_) {}
00644 virtual size_t size(void) const { return p.size(); }
00645
00646 virtual void impl_startSeek(seekBlock &s);
00647 virtual size_t impl_tell(seekBlock &s);
00648 virtual void impl_seek(seekBlock &s,size_t off);
00649 virtual void impl_endSeek(seekBlock &s);
00650 };
00651
00652
00653
00654
00655 class xlater : public wrap_er {
00656 protected:
00657 typedef void (*dataConverterFn)(int N,const myByte *in,myByte *out,size_t nElem);
00658
00659
00660
00661
00662 dataConverterFn convertFn[dataType_last];
00663
00664 size_t convertSize[dataType_last];
00665 void setConverterInt(const machineInfo &m,const machineInfo &cur,
00666 int isUnsigned,int intType,dataType dest);
00667
00668
00669 virtual void bytes(void *p,size_t n,size_t itemSize,dataType t);
00670 public:
00671 xlater(const machineInfo &fromMachine, er &fromData);
00672 };
00673
00674
00675
00676 class able {
00677 public:
00678
00679 class PUP_ID {
00680 public:
00681 enum {len=8};
00682 unsigned char hash[len];
00683 PUP_ID() {}
00684 PUP_ID(int val) {for (int i=0;i<len;i++) hash[i]=val;}
00685 PUP_ID(const char *name) {setName(name);}
00686 void setName(const char *name);
00687 bool operator==(const PUP_ID &other) const {
00688 for (int i=0;i<len;i++)
00689 if (hash[i]!=other.hash[i])
00690 return false;
00691 return true;
00692 }
00693 void pup(er &p) {
00694 p((char *)hash,sizeof(unsigned char)*len);
00695 }
00696 void pup(er &p) const {
00697 p((char *)hash,sizeof(unsigned char)*len);
00698 }
00699 };
00700
00701 protected:
00702 able() {}
00703 able(CkMigrateMessage *) {}
00704 virtual ~able();
00705
00706 public:
00707
00708 typedef able* (*constructor_function)(void);
00709 static PUP_ID register_constructor(const char *className,
00710 constructor_function fn);
00711 static constructor_function get_constructor(const PUP_ID &id);
00712 virtual able *clone(void) const;
00713
00714
00715 virtual void pup(er &p);
00716 virtual const PUP_ID &get_PUP_ID(void) const=0;
00717 };
00718
00719 #define SINGLE_ARG(...) __VA_ARGS__
00720
00721
00722
00723 #define PUPable_operator_inside(className)\
00724 friend inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
00725 friend inline void operator|(PUP::er &p,className* &a) {\
00726 PUP::able *pa=a; p(&pa); a=dynamic_cast<className *>(pa);\
00727 }
00728
00729
00730 #define PUPable_operator_outside(className)\
00731 inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
00732 inline void operator|(PUP::er &p,className* &a) {\
00733 PUP::able *pa=a; p(&pa); a=dynamic_cast<className *>(pa);\
00734 }
00735
00736
00737
00738 #define PUPable_decl(className) \
00739 PUPable_decl_inside(className) \
00740 PUPable_operator_inside(className)
00741
00742 #define PUPable_decl_template(className) \
00743 PUPable_decl_inside_template(SINGLE_ARG(className)) \
00744 PUPable_operator_inside(SINGLE_ARG(className))
00745
00746
00747 #define PUPable_decl_inside(className) \
00748 private: \
00749 static PUP::able *call_PUP_constructor(void); \
00750 static PUP::able::PUP_ID my_PUP_ID;\
00751 public:\
00752 virtual const PUP::able::PUP_ID &get_PUP_ID(void) const; \
00753 static void register_PUP_ID(const char* name);
00754
00755 #define PUPable_decl_base_template(baseClassName, className) \
00756 PUPable_decl_inside_base_template(SINGLE_ARG(baseClassName), \
00757 SINGLE_ARG(className)) \
00758 PUPable_operator_inside(SINGLE_ARG(className))
00759
00760 #define PUPable_decl_inside_template(className) \
00761 private: \
00762 static PUP::able* call_PUP_constructor(void) { \
00763 return new className((CkMigrateMessage *)0);} \
00764 static PUP::able::PUP_ID my_PUP_ID;\
00765 public: \
00766 virtual const PUP::able::PUP_ID &get_PUP_ID(void) const { \
00767 return my_PUP_ID; } \
00768 static void register_PUP_ID(const char* name) { \
00769 my_PUP_ID=register_constructor(name,call_PUP_constructor);}
00770
00771 #define PUPable_decl_inside_base_template(baseClassName, className) \
00772 private: \
00773 static PUP::able *call_PUP_constructor(void) { \
00774 return new className((CkMigrateMessage *)0); \
00775 } \
00776 static PUP::able::PUP_ID my_PUP_ID; \
00777 \
00778 public: \
00779 virtual const PUP::able::PUP_ID &get_PUP_ID(void) const { \
00780 return my_PUP_ID; \
00781 } \
00782 static void register_PUP_ID(const char *name) { \
00783 my_PUP_ID = \
00784 baseClassName::register_constructor(name, call_PUP_constructor); \
00785 }
00786
00787
00788 #define PUPable_decl_outside(className) \
00789 PUPable_operator_outside(className)
00790
00791
00792 #define PUPable_decl_outside_template(templateParameters,className) \
00793 template<templateParameters> inline void operator|(PUP::er &p,className &a) {a.pup(p);} \
00794 template<templateParameters> inline void operator|(PUP::er &p,className* &a) { \
00795 PUP::able *pa=a; p(&pa); a=(className *)pa; } \
00796 template<templateParameters> PUP::able *className::call_PUP_constructor(void) { \
00797 return new className((CkMigrateMessage *)0);} \
00798 template<templateParameters> const PUP::able::PUP_ID &className::get_PUP_ID(void) const { \
00799 return className::my_PUP_ID; } \
00800 template<templateParameters> void className::register_PUP_ID(const char* name) { \
00801 my_PUP_ID=register_constructor(name,className::call_PUP_constructor);}
00802
00803
00804
00805
00806 #define PUPable_abstract(className) \
00807 public:\
00808 virtual const PUP::able::PUP_ID &get_PUP_ID(void) const =0; \
00809 PUPable_operator_inside(className)
00810
00811
00812 #define PUPable_def(className) \
00813 PUP::able *className::call_PUP_constructor(void) \
00814 { return new className((CkMigrateMessage *)0);}\
00815 const PUP::able::PUP_ID &className::get_PUP_ID(void) const\
00816 { return className::my_PUP_ID; }\
00817 PUP::able::PUP_ID className::my_PUP_ID;\
00818 void className::register_PUP_ID(const char* name)\
00819 {my_PUP_ID=register_constructor(name,\
00820 className::call_PUP_constructor);}
00821
00822
00823 #define PUPable_def_template(className) \
00824 template<> PUP::able::PUP_ID className::my_PUP_ID = 0;
00825
00826
00827 #define PUPable_def_template_nonInst(className) \
00828 PUP::able::PUP_ID className::my_PUP_ID = 0;
00829
00830
00831 #define PUPable_reg(className) \
00832 className::register_PUP_ID(#className);
00833 #define PUPable_reg2(classIdentifier,className) \
00834 classIdentifier::register_PUP_ID(className);
00835
00836 inline void operator|(er &p,able &a) {a.pup(p);}
00837 inline void operator|(er &p,able* &a) {p(&a);}
00838 }
00839
00840
00841
00842
00843
00844
00845
00846 template <class T>
00847 class CkPointer {
00848 T *allocated;
00849 T *ptr;
00850
00851 CkPointer(const CkPointer<T> &) = delete;
00852 void operator=(const CkPointer<T> &) = delete;
00853 void operator=(CkPointer<T> &&) = delete;
00854 protected:
00855 T *peek(void) {return ptr;}
00856 public:
00858 CkPointer(T *src)
00859 {
00860 allocated=0;
00861 ptr=src;
00862 }
00863 CkPointer(CkPointer<T> &&src)
00864 {
00865 allocated = src.allocated;
00866 ptr = src.ptr;
00867
00868 src.allocated = nullptr;
00869 src.ptr = nullptr;
00870 }
00871
00873 CkPointer(void) {
00874 ptr=allocated=0;
00875 }
00876
00877 ~CkPointer() { if (allocated) delete allocated; }
00878
00881 inline operator T* () { allocated=0; return ptr; }
00882
00883 inline void pup(PUP::er &p) {
00884 bool ptrWasNull=(ptr==0);
00885
00886 PUP::able *ptr_able=ptr;
00887 p|ptr_able;
00888 ptr=(T *)ptr_able;
00889
00890 if (ptrWasNull)
00891 {
00892
00893 allocated=ptr;
00894 }
00895 }
00896 friend inline void operator|(PUP::er &p,CkPointer<T> &v) {v.pup(p);}
00897 };
00898 #define PUPable_marshall CkPointer
00899
00900
00901
00902 template<class T>
00903 class CkReference : private CkPointer<T> {
00904 public:
00906 CkReference(T &src)
00907 :CkPointer<T>(&src) { }
00908
00910 CkReference(void) {}
00911
00914 inline operator T& () { return *this->peek(); }
00915
00916 inline void pup(PUP::er &p) {CkPointer<T>::pup(p);}
00917
00918 friend inline void operator|(PUP::er &p,CkReference<T> &v) {v.pup(p);}
00919 };
00920
00921
00922 typedef PUP::er PUPer;
00923 typedef PUP::able PUPable;
00924
00925
00926
00927
00928
00929
00930
00931
00932 namespace PUP {
00940 template<class T> class as_bytes {
00941 #ifdef CK_DEFAULT_BITWISE_PUP
00942 public: enum {value=1};
00943 #else
00944 public: enum {value=0};
00945 #endif
00946 };
00947
00948
00949 #ifdef CK_DEFAULT_BITWISE_PUP
00951 template <class T>
00952 inline void operator|(PUP::er &p,T &t) {p((void *)&t,sizeof(T));}
00953 template <class T>
00954 inline void PUParray(PUP::er &p,T *ta,size_t n) { p((void *)ta,n*sizeof(T)); }
00955
00956
00957 # define PUPmarshall(type) \
00958 template<class T> inline void operator|(PUP::er &p,T &t) { t.pup(p); } \
00959 template<class T> inline void PUParray(PUP::er &p,T *t,size_t n) { \
00960 for (size_t i=0;i<n;i++) p|t[i]; \
00961 }
00962
00963 #else
00964
00965
00966 namespace details {
00967
00968 template <typename... Ts>
00969 struct make_void {
00970 typedef void type;
00971 };
00972 template <typename... Ts>
00973 using void_t = typename make_void<Ts...>::type;
00974
00975 template <typename T, typename U = void>
00976 struct is_pupable : std::false_type {};
00977
00978 template <typename T>
00979 struct is_pupable<
00980 T, void_t<decltype(std::declval<T>().pup(std::declval<PUP::er &>()))>>
00981 : std::true_type {};
00982
00983 }
00984
00988 template <class T, typename std::enable_if<details::is_pupable<T>::value, int>::type = 0>
00989 inline void operator|(PUP::er &p, T &t) {
00990 p.syncComment(PUP::sync_begin_object);
00991 t.pup(p);
00992 p.syncComment(PUP::sync_end_object);
00993 }
00994
00998 template<class T>
00999 inline void PUParray(PUP::er &p,T *t,size_t n) {
01000 p.syncComment(PUP::sync_begin_array);
01001 for (size_t i=0;i<n;i++) {
01002 p.syncComment(PUP::sync_item);
01003 p|t[i];
01004 }
01005 p.syncComment(PUP::sync_end_array);
01006 }
01007
01008
01009 # define PUPmarshall(type)
01010 #endif
01011 #define PUPmarshal(type) PUPmarshall(type)
01012
01013
01015 #define PUPbytes(type) \
01016 namespace PUP { inline void operator|(PUP::er &p,type &t) {p((char *)&t,sizeof(type));} } \
01017 namespace PUP { inline void PUParray(PUP::er &p,type *ta,size_t n) { p((char *)ta,n*sizeof(type)); } } \
01018 namespace PUP { template<> class as_bytes<type> { \
01019 public: enum {value=1}; \
01020 }; }
01021 #define PUPmarshallBytes(type) PUPbytes(type)
01022
01024 #define PUPfunctionpointer(fnPtrType) \
01025 inline void operator|(PUP::er &p,fnPtrType &t) {p((char *)&t,sizeof(fnPtrType));}
01026
01028 #define PUPenum(enumType) \
01029 inline void operator|(PUP::er &p,enumType &e) { int v=e; p|v; e=v; }
01030
01031 }
01032
01037 #define PUP_BUILTIN_SUPPORT(type) \
01038 namespace PUP { inline void operator|(er &p,type &t) {p(t);} } \
01039 namespace PUP { inline void PUParray(er &p,type *ta,size_t n) { p(ta,n); } } \
01040 namespace PUP { template<> class as_bytes<type> { \
01041 public: enum {value=1}; \
01042 }; }
01043 PUP_BUILTIN_SUPPORT(signed char)
01044 #if CMK_SIGNEDCHAR_DIFF_CHAR
01045 PUP_BUILTIN_SUPPORT(char)
01046 #endif
01047 PUP_BUILTIN_SUPPORT(unsigned char)
01048 PUP_BUILTIN_SUPPORT(short)
01049 PUP_BUILTIN_SUPPORT(int)
01050 PUP_BUILTIN_SUPPORT(long)
01051 PUP_BUILTIN_SUPPORT(unsigned short)
01052 PUP_BUILTIN_SUPPORT(unsigned int)
01053 PUP_BUILTIN_SUPPORT(unsigned long)
01054 PUP_BUILTIN_SUPPORT(float)
01055 PUP_BUILTIN_SUPPORT(double)
01056 PUP_BUILTIN_SUPPORT(bool)
01057 #if CMK_LONG_DOUBLE_DEFINED
01058 PUP_BUILTIN_SUPPORT(long double)
01059 #endif
01060 #ifdef CMK_PUP_LONG_LONG
01061 PUP_BUILTIN_SUPPORT(CMK_PUP_LONG_LONG)
01062 PUP_BUILTIN_SUPPORT(unsigned CMK_PUP_LONG_LONG)
01063 #endif
01064 #if CMK_HAS_INT16
01065 PUP_BUILTIN_SUPPORT(CmiInt16)
01066 PUP_BUILTIN_SUPPORT(CmiUInt16)
01067 #endif
01068
01069
01070
01071
01072
01073 #define PUPn(field) \
01074 do{ if (p.hasComments()) p.comment(#field); p|field; } while(0)
01075
01076
01077 #define PUPv(field,len) \
01078 do{ if (p.hasComments()) p.comment(#field); PUParray(p,field,len); } while(0)
01079
01080
01081 #endif //def __CK_PUP_H
01082
01083