Document that zero copy api mostly offers only memory footprint benefit
[charm.git] / doc / charm++ / advancedpup.tex
blob5ea962a74c56c360095e506fb90137952133155f
1 This section describes advanced functionality in the PUP framework.
2 The first subsections describes features supporting complex objects,
3 with multiple levels of inheritance, or with dynamic changes in heap
4 usage. The latter subsections describe additional language bindings,
5 and features supporting PUP modes which can be used to copy object
6 state from and to long term storage for checkpointing, or other
7 application level purposes.
9 \section{Dynamic Allocation}
10 \label{sec:pupdynalloc}
12 If your class has fields that are dynamically allocated, when unpacking
13 these need to be allocated (in the usual way) before you pup them.
14 Deallocation should be left to the class destructor as usual.
16 \subsection{No allocation}
18 The simplest case is when there is no dynamic allocation.
19 \begin{alltt}
20 class keepsFoo : public mySuperclass \{
21 private:
22 foo f; /* simple foo object*/
23 public:
24 keepsFoo(void) \{ \}
25 void pup(PUP::er &p) \{
26 mySuperclass::pup(p);
27 p|f; // pup f's fields (calls f.pup(p);)
29 ~keepsFoo() \{ \}
30 \};
31 \end{alltt}
33 \subsection{Allocation outside pup}
35 The next simplest case is when we contain a class
36 that is always allocated during our constructor,
37 and deallocated during our destructor. Then no allocation
38 is needed within the pup routine.
39 \begin{alltt}
40 class keepsHeapFoo : public mySuperclass \{
41 private:
42 foo *f; /*Heap-allocated foo object*/
43 public:
44 keepsHeapFoo(void) \{
45 f=new foo;
47 void pup(PUP::er &p) \{
48 mySuperclass::pup(p);
49 p|*f; // pup f's fields (calls f->pup(p))
51 ~keepsHeapFoo() \{delete f;\}
52 \};
53 \end{alltt}
55 \subsection{Allocation during pup}
57 If we need values obtained during the pup routine
58 before we can allocate the class, we must
59 allocate the class inside the pup routine.
60 Be sure to protect the allocation with ``if (p.isUnpacking())''.
61 \begin{alltt}
62 class keepsOneFoo : public mySuperclass \{
63 private:
64 foo *f; /*Heap-allocated foo object*/
65 public:
66 keepsOneFoo(...) \{f=new foo(...);\}
67 keepsOneFoo() \{f=NULL;\} /* pup constructor */
68 void pup(PUP::er &p) \{
69 mySuperclass::pup(p);
70 ...
71 if (p.isUnpacking()) /* must allocate foo now */
72 f=new foo(...);
73 p|*f;//pup f's fields
75 ~keepsOneFoo() \{delete f;\}
76 \};
77 \end{alltt}
79 \subsection{Allocatable array}
81 For example, if we keep an array of doubles,
82 we need to know how many doubles there are
83 before we can allocate the array. Hence we must
84 first pup the array length, do our allocation,
85 and then pup the array data. We could allocate memory using
86 malloc/free or other allocators in exactly the same way.
87 \begin{alltt}
88 class keepsDoubles : public mySuperclass \{
89 private:
90 int n;
91 double *arr;/*new'd array of n doubles*/
92 public:
93 keepsDoubles(int n_) \{
94 n=n_;
95 arr=new double[n];
97 keepsDoubles() \{ \}
99 void pup(PUP::er &p) \{
100 mySuperclass::pup(p);
101 p|n;//pup the array length n
102 if (p.isUnpacking()) arr=new double[n];
103 PUParray(p,arr,n); //pup data in the array
106 ~keepsDoubles() \{delete[] arr;\}
108 \end{alltt}
110 \subsection{NULL object pointer}
112 If our allocated object may be NULL, our allocation
113 becomes much more complicated. We must first check
114 and pup a flag to indicate whether the object exists,
115 then depending on the flag, pup the object.
116 \begin{alltt}
117 class keepsNullFoo : public mySuperclass \{
118 private:
119 foo *f; /*Heap-allocated foo object, or NULL*/
120 public:
121 keepsNullFoo(...) \{ if (...) f=new foo(...);\}
122 keepsNullFoo() \{f=NULL;\}
123 void pup(PUP::er &p) \{
124 mySuperclass::pup(p);
125 int has_f=(f!=NULL);
126 p|has_f;
127 if (has_f) \{
128 if (p.isUnpacking()) f=new foo;
129 p|*f;
130 \} else \{
131 f=NULL;
134 ~keepsNullFoo() \{delete f;\}
136 \end{alltt}
138 This sort of code is normally much longer and more
139 error-prone if split into the various packing/unpacking cases.
141 \subsection{Array of classes}
143 An array of actual classes can be treated exactly the same way
144 as an array of basic types. PUParray will pup each
145 element of the array properly, calling the appropriate \verb.operator|..
146 \begin{alltt}
147 class keepsFoos : public mySuperclass \{
148 private:
149 int n;
150 foo *arr;/*new'd array of n foos*/
151 public:
152 keepsFoos(int n_) \{
153 n=n_;
154 arr=new foo[n];
156 keepsFoos() \{ arr=NULL; \}
158 void pup(PUP::er &p) \{
159 mySuperclass::pup(p);
160 p|n;//pup the array length n
161 if (p.isUnpacking()) arr=new foo[n];
162 PUParray(p,arr,n); //pup each foo in the array
165 ~keepsFoos() \{delete[] arr;\}
167 \end{alltt}
170 \subsection{Array of pointers to classes}
172 An array of pointers to classes must handle each element
173 separately, since the PUParray routine does not work with
174 pointers. An ``allocate'' routine to set up the array
175 could simplify this code. More ambitious is to construct
176 a ``smart pointer'' class that includes a pup routine.
177 \begin{alltt}
178 class keepsFooPtrs : public mySuperclass \{
179 private:
180 int n;
181 foo **arr;/*new'd array of n pointer-to-foos*/
182 public:
183 keepsFooPtrs(int n_) \{
184 n=n_;
185 arr=new foo*[n]; // allocate array
186 for (int i=0;i<n;i++) arr[i]=new foo(...); // allocate i'th foo
188 keepsFooPtrs() \{ arr=NULL; \}
190 void pup(PUP::er &p) \{
191 mySuperclass::pup(p);
192 p|n;//pup the array length n
193 if (p.isUnpacking()) arr=new foo*[n]; // allocate array
194 for (int i=0;i<n;i++) \{
195 if (p.isUnpacking()) arr[i]=new foo(...); // allocate i'th foo
196 p|*arr[i]; //pup the i'th foo
200 ~keepsFooPtrs() \{
201 for (int i=0;i<n;i++) delete arr[i];
202 delete[] arr;
205 \end{alltt}
207 Note that this will not properly handle the case where
208 some elements of the array are actually subclasses of foo,
209 with virtual methods. The PUP::able framework described
210 in the next section can be helpful in this case.
213 \section{Subclass allocation via PUP::able}
215 \label{sec:pup::able}
216 If the class \uw{foo} above might have been a subclass, instead of
217 simply using \uw{new foo} above we would have had to allocate
218 an object of the appropriate subclass. Since determining the
219 proper subclass and calling the appropriate constructor yourself can be
220 difficult, the PUP framework provides a scheme for automatically
221 determining and dynamically allocating subobjects of the appropriate type.
223 Your superclass must inherit from \kw{PUP::able}, which provides
224 the basic machinery used to move the class.
225 A concrete superclass and all its concrete subclasses require these
226 four features:
228 \begin{itemize}
229 \item A line declaring \kw{PUPable \uw{className};} in the .ci file.
230 This registers the class's constructor.
232 \item A call to the macro \kw{PUPable\_decl(\uw{className})} in the
233 class's declaration, in the header file. This adds a virtual
234 method to your class to allow \kw{PUP::able} to determine your class's type.
236 \item A migration constructor---a constructor that takes \kw{CkMigrateMessage *}.
237 This is used to create the new object on the receive side, immediately
238 before calling the new object's \kw{pup} routine.
240 \item A working, virtual \kw{pup} method. You can omit this if your
241 class has no data that needs to be packed.
242 \end{itemize}
244 An abstract superclass---a superclass that will never actually be
245 packed---only needs to inherit from \kw{PUP::able} and include a
246 \kw{PUPable\_abstract(\uw{className})} macro in their body. For
247 these abstract classes, the
248 .ci file, \kw{PUPable\_decl} macro, and constructor are not needed.
250 For example, if \uw{parent} is a concrete superclass and \uw{child} its
251 subclass,
253 \begin{alltt}
254 //In the .ci file:
255 PUPable parent;
256 PUPable child; //Could also have said ``PUPable parent, child;''
258 //In the .h file:
259 class parent : public PUP::able \{
260 ... data members ...
261 public:
262 ... other methods ...
263 parent() \{...\}
265 //PUP::able support: decl, migration constructor, and pup
266 PUPable\_decl(parent);
267 parent(CkMigrateMessage *m) : PUP::able(m) \{\}
268 virtual void pup(PUP::er &p) \{
269 PUP::able::pup(p);//Call base class
270 ... pup data members as usual ...
273 class child : public parent \{
274 ... more data members ...
275 public: ... more methods, possibly virtual ...
276 child() \{...\}
278 //PUP::able support: decl, migration constructor, and pup
279 PUPable\_decl(child);
280 child(CkMigrateMessage *m) : parent(m) \{\}
281 virtual void pup(PUP::er &p) \{
282 parent::pup(p);//Call base class
283 ... pup child's data members as usual ...
287 \end{alltt}
289 With these declarations, then, we can automatically
290 allocate and pup a pointer to a parent or child
291 using the vertical bar \kw{PUP::er} syntax, which on the receive
292 side will create a new object of the appropriate type:
294 \begin{alltt}
295 class keepsParent \{
296 parent *obj; //May actually point to a child class (or be NULL)
297 public:
299 ~keepsParent() \{
300 delete obj;
302 void pup(PUP::er &p)
304 p|obj;
308 \end{alltt}
310 This will properly pack, allocate, and unpack obj whether
311 it is actually a parent or child object. The child class
312 can use all the usual \CC\ features, such as virtual functions
313 and extra private data.
315 If obj is NULL when packed, it will be restored to NULL when unpacked.
316 For example, if the nodes of a binary tree are \kw{PUP::able},
317 one may write a recursive pup routine for the tree quite easily:
319 \begin{alltt}
320 // In the .ci file:
321 PUPable treeNode;
323 // In the .h file
324 class treeNode : public PUP::able \{
325 treeNode *left;//Left subtree
326 treeNode *right;//Right subtree
327 ... other fields ...
328 public:
329 treeNode(treeNode *l=NULL, treeNode *r=NULL);
330 ~treeNode() \{delete left; delete right;\}
332 // The usual PUP::able support:
333 PUPable\_decl(treeNode);
334 treeNode(CkMigrateMessage *m) : PUP::able(m) \{ left=right=NULL; \}
335 void pup(PUP::er &p) \{
336 PUP::able::pup(p);//Call base class
337 p|left;
338 p|right;
339 ... pup other fields as usual ...
342 \end{alltt}
344 This same implementation will also work properly even if the tree's
345 internal nodes are actually subclasses of treeNode.
347 You may prefer to use the macros \kw{PUPable\_def(\uw{className})}
348 and \kw{PUPable\_reg(\uw{className})} rather than using \kw{PUPable}
349 in the .ci file. \kw{PUPable\_def} provides routine definitions used
350 by the \kw{PUP::able} machinery, and should be included in exactly one
351 source file at file scope. \kw{PUPable\_reg} registers this class
352 with the runtime system, and should be executed exactly once per node
353 during program startup.
355 Finally, a \kw{PUP::able} superclass like \uw{parent} above
356 must normally be passed around via a pointer or reference, because the object
357 might actually be some subclass like \uw{child}. Because
358 pointers and references cannot be passed across processors,
359 for parameter marshalling you must use the special templated
360 smart pointer classes \kw{CkPointer} and \kw{CkReference},
361 which only need to be listed in the .ci file.
363 A \kw{CkReference} is a read-only reference to a \kw{PUP::able} object---it
364 is only valid for the duration of the method call. A \kw{CkPointer}
365 transfers ownership of the unmarshalled \kw{PUP::able} to the method, so the
366 pointer can be kept and the object used indefinitely.
368 For example, if the entry method \uw{bar} needs a \kw{PUP::able} \uw{parent}
369 object for in-call processing, you would use a \kw{CkReference} like this:
371 \begin{alltt}
372 // In the .ci file:
373 entry void barRef(int x,CkReference<parent> p);
375 // In the .h file:
376 void barRef(int x,parent &p) \{
377 // can use p here, but only during this method invocation
379 \end{alltt}
381 If the entry method needs to keep its parameter, use a \kw{CkPointer} like this:
382 \begin{alltt}
383 // In the .ci file:
384 entry void barPtr(int x,CkPointer<parent> p);
386 // In the .h file:
387 void barPtr(int x,parent *p) \{
388 // can keep this pointer indefinitely, but must eventually delete it
390 \end{alltt}
392 Both \kw{CkReference} and \kw{CkPointer} are read-only from the send
393 side---unlike messages, which are consumed when sent, the same object
394 can be passed to several parameter marshalled entry methods.
395 In the example above, we could do:
397 \begin{alltt}
398 parent *p=new child;
399 someProxy.barRef(x,*p);
400 someProxy.barPtr(x,p); // Makes a copy of p
401 delete p; // We allocated p, so we destroy it.
402 \end{alltt}
405 \section{C and Fortran bindings}
407 C and Fortran programmers can use a limited subset of the
408 \kw{PUP::er} capability. The routines all take a
409 handle named \kw{pup\_er}. The routines
410 have the prototype:
411 \begin{alltt}
412 void pup\_\kw{type}(pup\_er p,\kw{type} *val);
413 void pup\_\kw{type}s(pup\_er p,\kw{type} *vals,int nVals);
414 \end{alltt}
415 The first call is for use with a single element;
416 the second call is for use with an array.
417 The supported types are char, short, int, long,
418 uchar, ushort, uint, ulong, float, and double,
419 which all have the usual C meanings.
421 A byte-packing routine
422 \begin{alltt}
423 void pup\_bytes(pup\_er p,void *data,int nBytes);
424 \end{alltt}
425 is also provided, but its use is discouraged
426 for cross-platform puping.
428 \kw{pup\_isSizing}, \kw{pup\_isPacking}, \kw{pup\_isUnpacking},
429 and \kw{pup\_isDeleting} calls are also available.
430 Since C and Fortran have no destructors, you should
431 actually deallocate all data when passed a deleting \kw{pup\_er}.
433 C and Fortran users cannot use \kw{PUP::able} objects,
434 seeking, or write custom \kw{PUP::er}s. Using the \CC\
435 interface is recommended.
439 \section{Common PUP::ers}
440 \label{sec:PUP:CommonPUPers}
441 The most common \kw{PUP::er}s used are \kw{PUP::sizer},
442 \kw{PUP::toMem}, and \kw{PUP::fromMem}. These are sizing,
443 packing, and unpacking \kw{PUP::er}s, respectively.
445 \kw{PUP::sizer} simply sums up the sizes of the native
446 binary representation of the objects it is passed.
447 \kw{PUP::toMem} copies the binary representation of the
448 objects passed into a preallocated contiguous memory buffer.
449 \kw{PUP::fromMem} copies binary data from a contiguous memory
450 buffer into the objects passed. All three support the
451 \kw{size} method, which returns the number of bytes used
452 by the objects seen so far.
454 Other common \kw{PUP::er}s are \kw{PUP::toDisk},
455 \kw{PUP::fromDisk}, and \kw{PUP::xlater}. The first
456 two are simple filesystem variants of the \kw{PUP::toMem}
457 and \kw{PUP::fromMem} classes; \kw{PUP::xlater} translates
458 binary data from an unpacking PUP::er into the machine's
459 native binary format, based on a \kw{machineInfo} structure
460 that describes the format used by the source machine.
462 An example of \kw{PUP::toDisk} is available in \examplerefdir{PUP/pupDisk}
464 \section{PUP::seekBlock}
466 It may rarely occur that you require items to be unpacked
467 in a different order than they are packed. That is, you
468 want a seek capability. \kw{PUP::er}s support a limited
469 form of seeking.
471 To begin a seek block, create a \kw{PUP::seekBlock} object
472 with your current PUP::er and the number of ``sections'' to
473 create. Seek to a (0-based) section number
474 with the seek method, and end the seeking with the endBlock method.
475 For example, if we have two objects A and B, where A's pup
476 depends on and affects some object B, we can pup the two with:
478 \begin{alltt}
479 void pupAB(PUP::er &p)
481 ... other fields ...
482 PUP::seekBlock s(p,2); //2 seek sections
483 if (p.isUnpacking())
484 \{//In this case, pup B first
485 s.seek(1);
486 B.pup(p);
488 s.seek(0);
489 A.pup(p,B);
491 if (!p.isUnpacking())
492 \{//In this case, pup B last
493 s.seek(1);
494 B.pup(p);
496 s.endBlock(); //End of seeking block
497 ... other fields ...
499 \end{alltt}
501 Note that without the seek block, A's fields would be unpacked
502 over B's memory, with disastrous consequences.
503 The packing or sizing path must traverse the seek sections
504 in numerical order; the unpack path may traverse them in any
505 order. There is currently a small fixed limit of 3 on the
506 maximum number of seek sections.
509 \section{Writing a PUP::er}
511 System-level programmers may occasionally find it useful to define
512 their own \kw{PUP::er} objects. The system \kw{PUP::er} class is
513 an abstract base class that funnels all incoming pup requests
514 to a single subroutine:
516 \begin{alltt}
517 virtual void bytes(void *p,int n,size\_t itemSize,dataType t);
518 \end{alltt}
520 The parameters are, in order, the field address, the number of items,
521 the size of each item, and the type of the items. The \kw{PUP::er}
522 is allowed to use these fields in any way. However, an isSizing
523 or isPacking PUP::er may not modify the referenced user data;
524 while an isUnpacking PUP::er may not read the original values of
525 the user data. If your PUP::er is not clearly packing (saving values
526 to some format) or unpacking (restoring values), declare it as
527 sizing \kw{PUP::er}.