5134b07da6f8c25002de82c16ac11e3cf7f4c12c
[charm.git] / src / util / pup.h
1 /*
2 Pack/UnPack Library for UIUC Parallel Programming Lab
3 Orion Sky Lawlor, olawlor@uiuc.edu, 4/5/2000
4
5 This library allows you to easily pack an array, structure,
6 or object into a memory buffer or disk file, and then read
7 the object back later.  The library can also handle translating
8 between different machine representations for integers and floats.
9
10 Originally, you had to write separate functions for buffer 
11 sizing, pack to memory, unpack from memory, pack to disk, and 
12 unpack from disk.  These functions all perform the exact same function--
13 namely, they list the members of the array, struct, or object.
14 Further, all the functions must agree, or the unpacked data will 
15 be garbage.  This library allows the user to write *one* function,
16 pup, which will perform all needed packing/unpacking.
17
18 A simple example is:
19 class foo {
20  private:
21   CmiBool isBar;
22   int x;
23   char y;
24   unsigned long z;
25   CkVec<double> q;
26  public:
27   ...
28   void pup(PUP::er &p) {
29     PUPn(isBar);
30     PUPn(x);PUPn(y);PUPn(z);
31     PUPn(q);
32   }
33 };
34
35 A more complex example is:
36 class bar {
37  private:
38   foo f;
39   int nArr;//Length of array below
40   double *arr;//Heap-allocated array
41  public:
42   ...
43   
44   void pup(PUP::er &p) {
45     PUPn(f); // <- automatically calls foo::pup
46     PUPn(nArr);
47     if (p.isUnpacking()) // <- must allocate array on other side.
48       arr=new double[nArr];
49     PUPv(arr,nArr); // <- special syntax for arrays of simple types
50   }
51 };
52 */
53
54 #ifndef __CK_PUP_H
55 #define __CK_PUP_H
56
57 #include <stdio.h> /*<- for "FILE *" */
58
59 #ifndef __cplusplus
60 #error "Use pup_c.h for C programs-- pup.h is for C++ programs"
61 #endif
62
63 #ifdef STANDALONE_PUP
64 #define CmiAbort(x) { printf(x); abort(); }
65 #else
66 #ifndef CHARM_H
67 #  include "converse.h" // <- for CmiBool, CMK_* defines
68 #endif
69 extern "C" void CmiAbort(const char *msg);
70 #endif
71
72 //We need CkMigrateMessage only to distinguish the migration
73 // constructor from all other constructors-- the type
74 // itself has no meaningful fields.
75 typedef struct {int is_only_a_name;} CkMigrateMessage;
76
77 namespace PUP {
78
79 #if CMK_LONG_LONG_DEFINED
80 #define CMK_PUP_LONG_LONG long long
81 #elif CMK___int64_DEFINED
82 #define CMK_PUP_LONG_LONG __int64
83 #endif
84
85  
86 //Item data types-- these are used to do byte swapping, etc.
87 typedef enum {
88 //(this list must exactly match that in PUPer_xlate)
89   Tchar=0,Tshort, Tint, Tlong, Tlonglong,
90   Tuchar,Tushort,Tuint,Tulong, Tulonglong,
91 #if CMK___int128_DEFINED
92   Tint128, Tuint128,
93 #endif
94   Tfloat,Tdouble,Tlongdouble,
95   Tbool,
96   Tbyte,
97   Tsync,
98   Tpointer,
99   dataType_last //<- for setting table lengths, etc.
100 } dataType;
101
102 //This should be a 1-byte unsigned type
103 typedef unsigned char myByte;
104
105 //Forward declarations
106 class er;
107 class able;
108
109 //Used for out-of-order unpacking
110 class seekBlock {
111         enum {maxSections=3};
112         int secTab[maxSections+1];//The start of each seek section
113         int nSec;//Number of sections; current section #
114         int secTabOff;//Start of the section table, relative to the seek block
115         er &p;
116         CmiBool hasEnded;
117 public:
118         //Constructor
119         seekBlock(er &Np,int nSections);
120         //Destructor
121         ~seekBlock();
122
123         //Seek to the given section number (0-based, less than nSections)
124         void seek(int toSection);
125         //Finish with this seeker (must be called)
126         void endBlock(void);
127
128         //An evil hack to avoid inheritance and virtual functions among seekers--
129         // stores the PUP::er specific block start information.
130         union {
131                 int off;
132                 long loff;
133                 const myByte *cptr;
134                 myByte *ptr;
135                 void *vptr;
136         } data;
137 };
138
139 //The abstract base class:  PUP::er.
140 class er {
141  private:
142   er(const er &p);//You don't want to copy PUP::er's.
143  protected:
144   /// These state bits describe various user-settable properties.
145   enum {IS_USERLEVEL=0x0004, // If set, this is *not* a migration pup-- it's something else.
146         IS_DELETING =0x0008, // If set, C & f90 objects should delete themselves after pup
147         IS_COMMENTS =0x0010,  // If set, this PUP::er wants comments and sync codes.
148         IS_RESTARTING=0x0020  // If set, it is during restarting
149   };
150   /// These state bits describe the PUP::er's direction.
151   enum {IS_SIZING   =0x0100,
152         IS_PACKING  =0x0200,
153         IS_UNPACKING=0x0400,
154         TYPE_MASK   =0xFF00
155   };
156   unsigned int PUP_er_state;
157 #if CMK_EXPLICIT
158   explicit /* Makes constructor below behave better */
159 #endif
160            er(unsigned int inType): PUP_er_state(inType) {} //You don't want to create raw PUP::er's.
161  public:
162   virtual ~er();//<- does nothing, but might be needed by some child
163
164   //State queries (exactly one of these will be true)
165   CmiBool isSizing(void) const {return (PUP_er_state&IS_SIZING)!=0?CmiTrue:CmiFalse;}
166   CmiBool isPacking(void) const {return (PUP_er_state&IS_PACKING)!=0?CmiTrue:CmiFalse;}
167   CmiBool isUnpacking(void) const {return (PUP_er_state&IS_UNPACKING)!=0?CmiTrue:CmiFalse;}
168   const char *  typeString() const;
169   unsigned int getStateFlags(void) const {return PUP_er_state;}
170
171   //This indicates that the pup routine should free memory during packing.
172   void becomeDeleting(void) {PUP_er_state|=IS_DELETING;}
173   CmiBool isDeleting(void) const {return (PUP_er_state&IS_DELETING)!=0?CmiTrue:CmiFalse;}
174
175   //This indicates that the pup routine should not call system objects' pups.
176   void becomeUserlevel(void) {PUP_er_state|=IS_USERLEVEL;}
177   CmiBool isUserlevel(void) const {return (PUP_er_state&IS_USERLEVEL)!=0?CmiTrue:CmiFalse;}
178   
179   //This indicates that the pup routine should not call system objects' pups.
180   void becomeRestarting(void) {PUP_er_state|=IS_RESTARTING;}
181   CmiBool isRestarting(void) const {return (PUP_er_state&IS_RESTARTING)!=0?CmiTrue:CmiFalse;}
182   
183   CmiBool hasComments(void) const {return (PUP_er_state&IS_COMMENTS)!=0?CmiTrue:CmiFalse;}
184
185 //For single elements, pretend it's an array containing one element
186   void operator()(signed char &v)     {(*this)(&v,1);}
187 #if CMK_SIGNEDCHAR_DIFF_CHAR
188   void operator()(char &v)            {(*this)(&v,1);}
189 #endif
190   void operator()(short &v)           {(*this)(&v,1);}
191   void operator()(int &v)             {(*this)(&v,1);}
192   void operator()(long &v)            {(*this)(&v,1);}
193   void operator()(unsigned char &v)   {(*this)(&v,1);}
194   void operator()(unsigned short &v)  {(*this)(&v,1);}
195   void operator()(unsigned int &v)    {(*this)(&v,1);}
196   void operator()(unsigned long &v)   {(*this)(&v,1);}
197   void operator()(float &v)           {(*this)(&v,1);}
198   void operator()(double &v)          {(*this)(&v,1);}
199 #if CMK_LONG_DOUBLE_DEFINED
200   void operator()(long double &v)     {(*this)(&v,1);}
201 #endif
202   void operator()(CmiBool &v)         {(*this)(&v,1);}
203 #ifdef CMK_PUP_LONG_LONG
204   void operator()(CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
205   void operator()(unsigned CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
206 #endif
207 #if CMK___int128_DEFINED
208   void operator()(__int128 &v) {(*this)(&v,1);}
209   void operator()(unsigned __int128 &v) {(*this)(&v,1);}
210 #endif
211   void operator()(void* &v,void* sig) {(*this)(&v,1,sig);}
212   
213 //For arrays:
214   //Integral types:
215   void operator()(signed char *a,int nItems)
216     {bytes((void *)a,nItems,sizeof(signed char),Tchar);}
217 #if CMK_SIGNEDCHAR_DIFF_CHAR
218   void operator()(char *a,int nItems)
219     {bytes((void *)a,nItems,sizeof(char),Tchar);}
220 #endif
221   void operator()(short *a,int nItems)
222     {bytes((void *)a,nItems,sizeof(short),Tshort);}
223   void operator()(int *a,int nItems)
224     {bytes((void *)a,nItems,sizeof(int),Tint);}
225   void operator()(long *a,int nItems)
226     {bytes((void *)a,nItems,sizeof(long),Tlong);}
227
228   //Unsigned integral types:
229   void operator()(unsigned char *a,int nItems)
230     {bytes((void *)a,nItems,sizeof(unsigned char),Tuchar);}
231   void operator()(unsigned short *a,int nItems)
232     {bytes((void *)a,nItems,sizeof(unsigned short),Tushort);}
233   void operator()(unsigned int *a,int nItems)
234     {bytes((void *)a,nItems,sizeof(unsigned int),Tuint);}
235   void operator()(unsigned long *a,int nItems)
236     {bytes((void *)a,nItems,sizeof(unsigned long),Tulong);}
237
238   //Floating-point types:
239   void operator()(float *a,int nItems)
240     {bytes((void *)a,nItems,sizeof(float),Tfloat);}
241   void operator()(double *a,int nItems)
242     {bytes((void *)a,nItems,sizeof(double),Tdouble);}
243
244 #if CMK_LONG_DOUBLE_DEFINED
245   void operator()(long double *a,int nItems)
246     {bytes((void *)a,nItems,sizeof(long double),Tlongdouble);}
247 #endif
248
249   //For bools:
250   void operator()(CmiBool *a,int nItems)
251     {bytes((void *)a,nItems,sizeof(CmiBool),Tbool);}
252
253 #ifdef CMK_PUP_LONG_LONG
254   void operator()(CMK_PUP_LONG_LONG *a,int nItems)
255     {bytes((void *)a,nItems,sizeof(CMK_PUP_LONG_LONG),Tlonglong);}
256   void operator()(unsigned CMK_PUP_LONG_LONG *a,int nItems)
257     {bytes((void *)a,nItems,sizeof(unsigned CMK_PUP_LONG_LONG),Tulonglong);}
258 #endif
259 #if CMK___int128_DEFINED
260   void operator()(__int128 *a,int nItems)
261     {bytes((void *)a,nItems,sizeof(__int128),Tint128);}
262   void operator()(unsigned __int128 *a,int nItems)
263     {bytes((void *)a,nItems,sizeof(unsigned __int128),Tuint128);}
264 #endif
265
266   //For pointers: the last parameter is to make it more difficult to call
267   //(should not be used in normal code as pointers may loose meaning across processor)
268   void operator()(void **a,int nItems,void *pointerSignature)
269     {bytes((void *)a,nItems,sizeof(void *),Tpointer);}
270   
271   //For raw memory (n gives number of bytes)
272 /*
273   // pup void * is error-prune, let's avoid it - Gengbin
274   void operator()(void *a,int nBytes)
275     {bytes((void *)a,nBytes,1,Tbyte);}
276 */
277
278   //For allocatable objects (system will new/delete object and call pup routine)
279   void operator()(able** a)
280     {object(a);}
281   //For pre- or stack-allocated PUP::able objects-- just call object's pup
282   void operator()(able& a);
283
284   /// A descriptive (but entirely optional) human-readable comment field
285   virtual void comment(const char *message);
286
287   /// A 32-bit "synchronization marker" (not human readable).
288   ///  Some standard codes are listed under PUP::sync_....
289   virtual void synchronize(unsigned int sync);
290   
291   /// Insert a synchronization marker and comment into the stream.
292   ///  Only applies if this PUP::er wants comments.
293   inline void syncComment(unsigned int sync,const char *message=0) {
294 #if CMK_ERROR_CHECKING
295         if (hasComments()) {
296                 synchronize(sync);
297                 if (message) comment(message);
298         }
299 #else
300         /* empty, to avoid expensive virtual function calls */
301 #endif
302   }
303
304   //Generic bottleneck: pack/unpack n items of size itemSize
305   // and data type t from p.  Desc describes the data item
306   virtual void bytes(void *p,int n,size_t itemSize,dataType t) =0;
307   virtual void object(able** a);
308
309   virtual int size(void) const { return 0; }
310   
311   //For seeking (pack/unpack in different orders)
312   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
313   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
314   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
315   virtual void impl_endSeek(seekBlock &s);/*End a seeking block*/
316
317   //See more documentation before PUP_cmiAllocSizer in pup_cmialloc.h
318   //Must be a CmiAlloced buf while packing
319   virtual void pupCmiAllocBuf(void **msg) 
320       {CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");}
321
322   //In case source is not CmiAlloced the size can be passed and any
323   //user buf can be converted into a cmialloc'ed buf
324   virtual void pupCmiAllocBuf(void **msg, int size)
325       {CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");}
326 };
327
328 /**
329  "Sync" codes are an extra channel to encode data in a pup stream, 
330  to indicate higher-order structures in the pup'd objects.
331  Sync codes must follow this grammar:
332    <obj> -> <obj> <obj> | <array> | <list>
333    <obj> -> begin (<obj> system) <obj> end
334    <array> -> begin <obj> (item <obj>)* end
335    <list> -> begin <obj> (index <obj> item <obj>)* end
336  This hack is used, e.g., by the debugger.
337 */
338 enum {
339   sync_builtin=0x70000000, // Built-in, standard sync codes begin here
340   sync_begin=sync_builtin+0x01000000, // Sync code at start of collection
341   sync_end=sync_builtin+0x02000000, // Sync code at end of collection
342   sync_last_system=sync_builtin+0x09000000, // Sync code at end of "system" portion of object
343   sync_array_m=0x00100000, // Linear-indexed (0..n) array-- use item to separate
344   sync_list_m=0x00200000, // Some other collection-- use index and item
345   sync_object_m=0x00300000, // Sync mask for general object
346   
347   sync_begin_array=sync_begin+sync_array_m,
348   sync_begin_list=sync_begin+sync_list_m, 
349   sync_begin_object=sync_begin+sync_object_m, 
350   
351   sync_end_array=sync_end+sync_array_m, 
352   sync_end_list=sync_end+sync_list_m, 
353   sync_end_object=sync_end+sync_object_m, 
354   
355   sync_item=sync_builtin+0x00110000, // Sync code for a list or array item
356   sync_index=sync_builtin+0x00120000, // Sync code for index of item in a list
357   
358   sync_last
359 };
360
361 /************** PUP::er -- Sizer ******************/
362 //For finding the number of bytes to pack (e.g., to preallocate a memory buffer)
363 class sizer : public er {
364  protected:
365   int nBytes;
366   //Generic bottleneck: n items of size itemSize
367   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
368  public:
369   //Write data to the given buffer
370   sizer(void):er(IS_SIZING),nBytes(0) {}
371   
372   //Return the current number of bytes to be packed
373   int size(void) const {return nBytes;}
374 };
375
376 template <class T>
377 inline int size(T &t) {
378         PUP::sizer p; p|t; return p.size();
379 }
380
381 /********** PUP::er -- Binary memory buffer pack/unpack *********/
382 class mem : public er { //Memory-buffer packers and unpackers
383  protected:
384   myByte *origBuf;//Start of memory buffer
385   myByte *buf;//Memory buffer (stuff gets packed into/out of here)
386   mem(unsigned int type,myByte *Nbuf):er(type),origBuf(Nbuf),buf(Nbuf) {}
387   mem(const mem &p);                    //You don't want to copy
388   void operator=(const mem &p);         // You don't want to copy
389
390   //For seeking (pack/unpack in different orders)
391   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
392   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
393   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
394  public:
395   //Return the current number of buffer bytes used
396   int size(void) const {return buf-origBuf;}
397 };
398
399 //For packing into a preallocated, presized memory buffer
400 class toMem : public mem {
401  protected:
402   //Generic bottleneck: pack n items of size itemSize from p.
403   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
404  public:
405   //Write data to the given buffer
406   toMem(void *Nbuf):mem(IS_PACKING,(myByte *)Nbuf) {}
407 };
408 template <class T>
409 inline void toMemBuf(T &t,void *buf,int len) {
410         PUP::toMem p(buf);
411         p|t;
412         if (p.size()!=len) CmiAbort("Size mismatch during PUP::toMemBuf!\n"
413                 "This means your pup routine doesn't match during sizing and packing");
414 }
415
416 //For unpacking from a memory buffer
417 class fromMem : public mem {
418  protected:
419   //Generic bottleneck: unpack n items of size itemSize from p.
420   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
421  public:
422   //Read data from the given buffer
423   fromMem(const void *Nbuf):mem(IS_UNPACKING,(myByte *)Nbuf) {}
424 };
425 template <class T>
426 inline void fromMemBuf(T &t,void *buf,int len) {
427         PUP::fromMem p(buf);
428         p|t;
429         if (p.size()!=len) CmiAbort("Size mismatch during PUP::fromMemBuf!\n"
430                 "This means your pup routine doesn't match during packing and unpacking");
431 }
432
433 /********** PUP::er -- Binary disk file pack/unpack *********/
434 class disk : public er {
435  protected:
436   FILE *F;//Disk file to read from/write to
437   disk(unsigned int type,FILE *f):er(type),F(f) {}
438   disk(const disk &p);                  //You don't want to copy
439   void operator=(const disk &p);        // You don't want to copy
440
441   //For seeking (pack/unpack in different orders)
442   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
443   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
444   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
445 };
446
447 //For packing to a disk file
448 class toDisk : public disk {
449  protected:
450   //Generic bottleneck: pack n items of size itemSize from p.
451   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
452  public:
453   // Write data to the given file pointer
454   // (must be opened for binary write)
455   // You must close the file yourself when done.
456   toDisk(FILE *f):disk(IS_PACKING,f) {}
457 };
458
459 //For unpacking from a disk file
460 class fromDisk : public disk {
461  protected:
462   //Generic bottleneck: unpack n items of size itemSize from p.
463   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
464  public:
465   // Read data from the given file pointer 
466   // (must be opened for binary read)
467   // You must close the file yourself when done.
468   fromDisk(FILE *f):disk(IS_UNPACKING,f) {}
469 };
470
471 /************** PUP::er -- Text *****************/
472 class toTextUtil : public er {
473  private:
474   char *cur; /*Current output buffer*/
475   int level; /*Indentation distance*/
476   void beginEnv(const char *type,int n=0);
477   void endEnv(const char *type);
478   char *beginLine(void);
479   void endLine(void);
480  protected:
481   virtual char *advance(char *cur)=0; /*Consume current buffer and return next*/
482   toTextUtil(unsigned int inType,char *buf);
483   toTextUtil(const toTextUtil &p);              //You don't want to copy
484   void operator=(const toTextUtil &p);          // You don't want to copy
485  public:
486   virtual void comment(const char *message);
487   virtual void synchronize(unsigned int m);
488  protected:
489   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
490   virtual void object(able** a);
491 };
492 /* Return the number of characters, including terminating NULL */
493 class sizerText : public toTextUtil {
494  private:
495   char line[1000];
496   int charCount; /*Total characters seen so far (not including NULL) */
497  protected:
498   virtual char *advance(char *cur);
499  public:
500   sizerText(void);
501   int size(void) const {return charCount+1; /*add NULL*/ }
502 };
503
504 /* Copy data to this C string, including terminating NULL. */
505 class toText : public toTextUtil {
506  private:
507   char *buf;
508   int charCount; /*Total characters written so far (not including NULL) */
509  protected:
510   virtual char *advance(char *cur);
511  public:
512   toText(char *outStr);
513   toText(const toText &p);                      //You don't want to copy
514   void operator=(const toText &p);              // You don't want to copy
515   int size(void) const {return charCount+1; /*add NULL*/ }
516 };
517
518 class toTextFile : public er {
519  protected:
520   FILE *f;
521   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
522  public:
523   //Begin writing to this file, which should be opened for ascii write.
524   // You must close the file yourself when done.
525   toTextFile(FILE *f_) :er(IS_PACKING), f(f_) {}
526   toTextFile(const toTextFile &p);              //You don't want to copy
527   void operator=(const toTextFile &p);          // You don't want to copy
528   virtual void comment(const char *message);
529 };
530 class fromTextFile : public er {
531  protected:
532   FILE *f;
533   int readInt(const char *fmt="%d");
534   unsigned int readUint(const char *fmt="%u");
535   CMK_TYPEDEF_INT8 readLongInt(const char *fmt="%lld");
536   double readDouble(void);
537   
538   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
539   virtual void parseError(const char *what);
540  public:
541   //Begin writing to this file, which should be opened for ascii read.
542   // You must close the file yourself when done.
543   fromTextFile(FILE *f_) :er(IS_UNPACKING), f(f_) {}
544   fromTextFile(const fromTextFile &p);          //You don't want to copy
545   void operator=(const fromTextFile &p);        // You don't want to copy
546   virtual void comment(const char *message);
547 };
548
549 /********** PUP::er -- Heterogenous machine pack/unpack *********/
550 //This object describes the data representation of a machine.
551 class machineInfo {
552  public:
553   typedef unsigned char myByte;
554   myByte magic[4];//Magic number (to identify machineInfo structs)
555   myByte version;//0-- current version
556
557   myByte intBytes[5]; //<- sizeof(char,short,int,long,int128)
558   myByte intFormat;//0-- big endian.  1-- little endian.
559
560   myByte floatBytes; //<- sizeof(...)
561   myByte doubleBytes;
562   myByte floatFormat;//0-- big endian IEEE.  1-- little endian IEEE.
563
564   myByte boolBytes;
565   myByte pointerBytes;
566
567   myByte padding[1];//Padding to 16 bytes
568
569   //Return true if our magic number is valid.
570   CmiBool valid(void) const;
571   //Return true if we differ from the current (running) machine.
572   CmiBool needsConversion(void) const;
573   
574   //Get a machineInfo for the current machine
575   static const machineInfo &current(void);
576 };
577
578 /// "Wrapped" PUP::er: forwards requests to another PUP::er.
579 class wrap_er : public er {
580 protected:
581         er &p;
582 public:
583         wrap_er(er &p_,unsigned int newFlags=0) :er(p_.getStateFlags()|newFlags), p(p_) {}
584         virtual int size(void) const { return p.size(); }
585         
586         virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
587         virtual int impl_tell(seekBlock &s); /*Give the current offset*/
588         virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
589         virtual void impl_endSeek(seekBlock &s);/*End a seeking block*/
590 };
591
592 //For translating some odd disk/memory representation into the 
593 // current machine representation.  (We really only need to
594 // translate during unpack-- "reader makes right".)
595 class xlater : public wrap_er {
596  protected:
597   typedef void (*dataConverterFn)(int N,const myByte *in,myByte *out,int nElem);
598   
599   //This table is indexed by dataType, and contains an appropriate
600   // conversion function to unpack a n-item array of the corresponding 
601   // data type (possibly in-place).
602   dataConverterFn convertFn[dataType_last];
603   //Maps dataType to source machine's dataSize
604   size_t convertSize[dataType_last];
605   void setConverterInt(const machineInfo &m,const machineInfo &cur,
606     int isUnsigned,int intType,dataType dest);
607   
608   //Generic bottleneck: unpack n items of size itemSize from p.
609   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
610  public:
611   xlater(const machineInfo &fromMachine, er &fromData);
612 };
613
614 /*************** PUP::able support ***************/
615 //The base class of system-allocatable objects with pup routines
616 class able {
617 public:
618         //A globally-unique, persistent identifier for an allocatable object
619         class PUP_ID {
620         public:
621                 enum {len=8};
622                 unsigned char hash[len];
623                 PUP_ID() {}
624                 PUP_ID(int val) {for (int i=0;i<len;i++) hash[i]=val;}
625                 PUP_ID(const char *name) {setName(name);}
626                 void setName(const char *name);//Write name into hash
627                 CmiBool operator==(const PUP_ID &other) const {
628                         for (int i=0;i<len;i++)
629                                 if (hash[i]!=other.hash[i])
630                                         return CmiFalse;
631                         return CmiTrue;
632                 }
633                 void pup(er &p) {
634                          p((char *)hash,sizeof(unsigned char)*len);
635                 }
636                 void pup(er &p) const {
637                          p((char *)hash,sizeof(unsigned char)*len);
638                 }
639         };
640
641 protected:
642         able() {}
643         able(CkMigrateMessage *) {}
644         virtual ~able();//Virtual destructor may be needed by some child
645
646 public:
647 //Constructor function registration:
648         typedef able* (*constructor_function)(void);
649         static PUP_ID register_constructor(const char *className,
650                 constructor_function fn);
651         static constructor_function get_constructor(const PUP_ID &id);
652         virtual /*PUP::*/able *clone(void) const;
653
654 //Target methods:
655         virtual void pup(er &p);
656         virtual const PUP_ID &get_PUP_ID(void) const=0;
657 };
658
659 //Declarations which create routines implemeting the | operator.
660 //  Macros to be used inside a class body.
661 #define PUPable_operator_inside(className)\
662     friend inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
663     friend inline void operator|(PUP::er &p,className* &a) {\
664         PUP::able *pa=a;  p(&pa);  a=(className *)pa;\
665     }
666
667 //  Macros to be used outside a class body.
668 #define PUPable_operator_outside(className)\
669     inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
670     inline void operator|(PUP::er &p,className* &a) {\
671         PUP::able *pa=a;  p(&pa);  a=(className *)pa;\
672     }
673
674 //Declarations to include in a PUP::able's body.
675 //  Convenient, but only usable if class is not inside a namespace.
676 #define PUPable_decl(className) \
677     PUPable_decl_inside(className) \
678     PUPable_operator_inside(className)
679
680 #define PUPable_decl_template(className) \
681     PUPable_decl_inside_template(className) \
682     PUPable_operator_inside(className)
683
684 //PUPable_decl for classes inside a namespace: inside body
685 #define PUPable_decl_inside(className) \
686 private: \
687     static PUP::able *call_PUP_constructor(void); \
688     static PUP::able::PUP_ID my_PUP_ID;\
689 public:\
690     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const; \
691     static void register_PUP_ID(const char* name);
692
693 #define PUPable_decl_inside_template(className) \
694 private: \
695     static PUP::able* call_PUP_constructor(void) { \
696         return new className((CkMigrateMessage *)0);}                   \
697     static PUP::able::PUP_ID my_PUP_ID;\
698 public: \
699     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const { \
700         return my_PUP_ID; }                                     \
701     static void register_PUP_ID(const char* name) { \
702         my_PUP_ID=register_constructor(name,call_PUP_constructor);}
703
704 //PUPable_decl for classes inside a namespace: in header at file scope
705 #define PUPable_decl_outside(className) \
706      PUPable_operator_outside(className)
707
708 //PUPable_decl for classes inside a namespace: in header at file scope
709 #define PUPable_decl_outside_template(templateParameters,className)     \
710      template<templateParameters> inline void operator|(PUP::er &p,className &a) {a.pup(p);} \
711      template<templateParameters> inline void operator|(PUP::er &p,className* &a) { \
712          PUP::able *pa=a;  p(&pa);  a=(className *)pa; } \
713      template<templateParameters> PUP::able *className::call_PUP_constructor(void) { \
714          return new className((CkMigrateMessage *)0);}                  \
715      template<templateParameters> const PUP::able::PUP_ID &className::get_PUP_ID(void) const { \
716          return className::my_PUP_ID; }                                 \
717      template<templateParameters> void className::register_PUP_ID(const char* name) { \
718          my_PUP_ID=register_constructor(name,className::call_PUP_constructor);}
719
720
721 //Declarations to include in an abstract PUP::able's body.
722 //  Abstract PUP::ables do not need def or reg.
723 #define PUPable_abstract(className) \
724 public:\
725     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const =0; \
726     PUPable_operator_inside(className)
727
728 //Definitions to include exactly once at file scope
729 #define PUPable_def(className) \
730         PUP::able *className::call_PUP_constructor(void) \
731                 { return new className((CkMigrateMessage *)0);}\
732         const PUP::able::PUP_ID &className::get_PUP_ID(void) const\
733                 { return className::my_PUP_ID; }\
734         PUP::able::PUP_ID className::my_PUP_ID;\
735         void className::register_PUP_ID(const char* name)\
736                 {my_PUP_ID=register_constructor(name,\
737                               className::call_PUP_constructor);}
738
739 //Definitions to include exactly once at file scope
740 #define PUPable_def_template(className) \
741         template<> PUP::able::PUP_ID className::my_PUP_ID = 0;
742
743 //Code to execute exactly once at program start time
744 #define PUPable_reg(className)  \
745     className::register_PUP_ID(#className);
746 #define PUPable_reg2(classIdentifier,className) \
747     classIdentifier::register_PUP_ID(className);
748
749
750 } //<- End namespace PUP
751
752 inline void operator|(PUP::er &p,PUP::able &a) {a.pup(p);}
753 inline void operator|(PUP::er &p,PUP::able* &a) {p(&a);}
754
755 //Holds a pointer to a (possibly dynamically allocated) PUP::able.
756 //  Extracting the pointer hands the deletion responsibility over.
757 //  This is used by parameter marshalling, which doesn't work well 
758 //  with bare pointers.
759 //   CkPointer<T> t   is the parameter-marshalling equivalent of   T *t
760 template <class T>
761 class CkPointer {
762         T *allocated; //Pointer that PUP dynamically allocated for us (recv only)
763         T *ptr; //Read-only pointer
764
765 #if 0 /* Private (do-not-use) copy constructor.  This prevents allocated from being
766          deleted twice--once in the original, and again in the copy.*/
767         CkPointer(const CkPointer<T> &src); // Don't use this!
768 #else /* Some compilers, like gcc3, have a hideous bug that causes them to *demand*
769          a public copy constructor when a class is used to initialize a const-reference
770          from a temporary.  The public copy constructor should never be called, though. */
771 public:
772         CkPointer(const CkPointer<T> &src) {
773                 CmiAbort("PUPable_marshall's cannot be passed by value.  Pass them only by reference!");
774         }
775         void operator=(const CkPointer<T> &src) {
776                 CmiAbort("PUPable_marshall's cannot be passed by value.  Pass them only by reference!");
777         }
778 #endif
779 protected:
780         T *peek(void) {return ptr;}
781 public:
782         /// Used on the send side, and does *not* delete the object.
783         CkPointer(T *src)  ///< Marshall this object.
784         { 
785                 allocated=0; //Don't ever delete src
786                 ptr=src;
787         }
788         
789         /// Begin completely empty: used on marshalling recv side.
790         CkPointer(void) { 
791                 ptr=allocated=0;
792         }
793         
794         ~CkPointer() { if (allocated) delete allocated; }
795         
796         /// Extract the object held by this class.  
797         ///  Deleting the pointer is now the user's responsibility
798         inline operator T* () { allocated=0; return ptr; }
799         
800         inline void pup(PUP::er &p) {
801                 bool ptrWasNull=(ptr==0);
802                 
803                 PUP::able *ptr_able=ptr; // T must inherit from PUP::able!
804                 p|ptr_able; //Pack as a PUP::able *
805                 ptr=(T *)ptr_able;
806                 
807                 if (ptrWasNull) 
808                 { //PUP just allocated a new object for us-- 
809                   // make sure it gets deleted eventually.
810                         allocated=ptr;
811                 }
812         }
813         friend inline void operator|(PUP::er &p,CkPointer<T> &v) {v.pup(p);}
814 };
815 #define PUPable_marshall CkPointer
816
817 //Like CkPointer, but keeps deletion responsibility forever.
818 //   CkReference<T> t  is the parameter-marshalling equivalent of   T &t
819 template<class T>
820 class CkReference : private CkPointer<T> {
821 public:
822         /// Used on the send side, and does *not* delete the object.
823         CkReference(T &src)   ///< Marshall this object.
824                 :CkPointer<T>(&src) { }
825         
826         /// Begin completely empty: used on the recv side.
827         CkReference(void) {}
828         
829         /// Look at the object held by this class.  Does *not* hand over
830         /// deletion responsiblity.
831         inline operator T& () { return *this->peek(); }
832         
833         inline void pup(PUP::er &p) {CkPointer<T>::pup(p);}
834         
835         friend inline void operator|(PUP::er &p,CkReference<T> &v) {v.pup(p);}
836 };
837
838 // For people that forget the "::"
839 typedef PUP::er PUPer;
840 typedef PUP::able PUPable;
841
842 /******** PUP via pipe: another way to access PUP::ers *****
843 The parameter marshalling system pups each variable v using just:
844      p|v;
845 Thus we need a "void operator|(PUP::er &p,T &v)" for all types
846 that work with parameter marshalling. 
847 */
848
849 namespace PUP {
850         /** 
851           Traits class: decide if the type T can be safely
852           pupped as raw bytes.  This is true of classes that
853           do not contain pointers and do not need pup routines.
854           Use this like:
855              if (PUP::as_bytes<someClass>::value) { ... }
856         */
857         template<class T> class as_bytes {
858 #ifdef CK_DEFAULT_BITWISE_PUP   /* OLD */
859                 public: enum {value=1};
860 #else /* normal case: don't pack as bytes by default */
861                 public: enum {value=0};
862 #endif
863         };
864 }
865
866 #ifdef CK_DEFAULT_BITWISE_PUP   /* OLD compatability mode*/
867 /// Default operator| and PUParray: copy as bytes.
868 template <class T>
869 inline void operator|(PUP::er &p,T &t) {p((void *)&t,sizeof(T));}
870 template <class T>
871 inline void PUParray(PUP::er &p,T *ta,int n) { p((void *)ta,n*sizeof(T)); }
872
873 /* enable normal pup mode from CK_DEFAULT_BITWISE_PUP */
874 #  define PUPmarshall(type) \
875 template<class T> inline void operator|(PUP::er &p,T &t) { t.pup(p); } \
876 template<class T> inline void PUParray(PUP::er &p,T *t,int n) { \
877         for (int i=0;i<n;i++) p|t[i]; \
878 }
879
880 #else /* !CK_DEFAULT_BITWISE_PUP */
881 /// Normal case: Call pup routines by default
882 /**
883   Default operator|: call pup routine.
884 */
885 template<class T>
886 inline void operator|(PUP::er &p,T &t) { 
887         p.syncComment(PUP::sync_begin_object);
888         t.pup(p);
889         p.syncComment(PUP::sync_end_object); 
890 }
891
892 /**
893   Default PUParray: pup each element.
894 */
895 template<class T>
896 inline void PUParray(PUP::er &p,T *t,int n) {
897         p.syncComment(PUP::sync_begin_array);
898         for (int i=0;i<n;i++) {
899                 p.syncComment(PUP::sync_item);
900                 p|t[i];
901         }
902         p.syncComment(PUP::sync_end_array);
903 }
904
905 /* PUPmarshall macro: now a deprecated no-op */
906 #  define PUPmarshall(type) /* empty, pup routines now the default */
907 #endif
908 #define PUPmarshal(type) PUPmarshall(type) /*Support this common misspelling*/
909
910
911 /// Copy this type as raw memory (like memcpy).
912 #define PUPbytes(type) \
913   inline void operator|(PUP::er &p,type &t) {p((char *)&t,sizeof(type));} \
914   inline void PUParray(PUP::er &p,type *ta,int n) { p((char *)ta,n*sizeof(type)); } \
915   namespace PUP { template<> class as_bytes<type> { \
916         public: enum {value=1};  \
917   }; }
918 #define PUPmarshallBytes(type) PUPbytes(type)
919
920 /// Make PUP work with this function pointer type, copied as raw bytes.
921 #define PUPfunctionpointer(fnPtrType) \
922   inline void operator|(PUP::er &p,fnPtrType &t) {p((char *)&t,sizeof(fnPtrType));}
923
924 /// Make PUP work with this enum type, copied as an "int".
925 #define PUPenum(enumType) \
926   inline void operator|(PUP::er &p,enumType &e) { int v=e;  p|v; e=v; }
927
928
929 /**
930   For all builtin types, like "int",
931   operator| and PUParray use p(t) and p(ta,n).
932 */
933 #define PUP_BUILTIN_SUPPORT(type) \
934   inline void operator|(PUP::er &p,type &t) {p(t);} \
935   inline void PUParray(PUP::er &p,type *ta,int n) { p(ta,n); } \
936   namespace PUP { template<> class as_bytes<type> { \
937         public: enum {value=1};  \
938   }; }
939 PUP_BUILTIN_SUPPORT(signed char)
940 #if CMK_SIGNEDCHAR_DIFF_CHAR
941 PUP_BUILTIN_SUPPORT(char)
942 #endif
943 PUP_BUILTIN_SUPPORT(unsigned char)
944 PUP_BUILTIN_SUPPORT(short)
945 PUP_BUILTIN_SUPPORT(int)
946 PUP_BUILTIN_SUPPORT(long)
947 PUP_BUILTIN_SUPPORT(unsigned short)
948 PUP_BUILTIN_SUPPORT(unsigned int)
949 PUP_BUILTIN_SUPPORT(unsigned long)
950 PUP_BUILTIN_SUPPORT(float)
951 PUP_BUILTIN_SUPPORT(double)
952 PUP_BUILTIN_SUPPORT(CmiBool)
953 #if CMK_LONG_DOUBLE_DEFINED
954 PUP_BUILTIN_SUPPORT(long double)
955 #endif
956 #ifdef CMK_PUP_LONG_LONG
957 PUP_BUILTIN_SUPPORT(CMK_PUP_LONG_LONG)
958 PUP_BUILTIN_SUPPORT(unsigned CMK_PUP_LONG_LONG)
959 #endif
960 #if CMK___int128_DEFINED
961 PUP_BUILTIN_SUPPORT(__int128)
962 PUP_BUILTIN_SUPPORT(unsigned __int128)
963 #endif
964
965
966 //This macro is useful in simple pup routines:
967 //  It's just p|x, but it also documents the *name* of the variable.
968 // You must have a PUP::er named p.
969 #define PUPn(field) \
970   do{  if (p.hasComments()) p.comment(#field); p|field; } while(0)
971
972 //Like PUPn(x), above, but for arrays.
973 #define PUPv(field,len) \
974   do{  if (p.hasComments()) p.comment(#field); PUParray(p,field,len); } while(0)
975
976
977 #endif //def __CK_PUP_H
978
979