Major reworking of pup section-- many more examples,
authorOrion Lawlor <olawlor@acm.org>
Fri, 16 Jul 2004 23:01:40 +0000 (23:01 +0000)
committerOrion Lawlor <olawlor@acm.org>
Fri, 16 Jul 2004 23:01:40 +0000 (23:01 +0000)
and now describes PUParray.

doc/charm++/fig/pup.eps [new file with mode: 0644]
doc/charm++/fig/pup.fig [new file with mode: 0644]
doc/charm++/fig/pup.png [new file with mode: 0644]
doc/charm++/pup.tex

diff --git a/doc/charm++/fig/pup.eps b/doc/charm++/fig/pup.eps
new file mode 100644 (file)
index 0000000..c5d01c7
--- /dev/null
@@ -0,0 +1,255 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: pup_state2.eps
+%%Creator: fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Fri Jul 16 12:06:46 2004
+%%For: olawlor@lawlcsar (Orion Lawlor)
+%%BoundingBox: 0 0 398 105
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 105 moveto 0 0 lineto 398 0 lineto 398 105 lineto closepath clip newpath
+-125.3 347.2 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+  bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+  4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Arc
+15.000 slw
+n 3977.0 5252.0 148.0 -0.8 90.8 arc
+gs col0 s gr
+
+% Polyline
+n 4125 5025 m
+ 4125 5250 l gs col0 s gr 
+% Polyline
+n 3975 5400 m
+ 3900 5400 l gs col0 s gr 
+% Arc
+n 4273.5 4348.0 148.5 179.2 -89.4 arc
+gs col0 s gr
+
+% Polyline
+n 4125 4350 m
+ 4125 4725 l gs col0 s gr 
+/Helvetica-Bold ff 180.00 scf sf
+5842 5231 m
+gs 1 -1 sc (p.isSizing\(\)) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+2992 5456 m
+gs 1 -1 sc (Pup Constructor) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+3367 4931 m
+gs 1 -1 sc (p.isUnpacking\(\)) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+2992 4256 m
+gs 1 -1 sc (User Constructor) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+5842 4781 m
+gs 1 -1 sc (User Methods) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+5857 5681 m
+gs 1 -1 sc (p.isPacking\(\)) dup sw pop 2 div neg 0 rm  col0 sh gr
+/Helvetica-Bold ff 180.00 scf sf
+8017 4256 m
+gs 1 -1 sc (Destructor) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Arc
+n 4873.5 4348.0 148.5 179.2 -89.4 arc
+gs col0 s gr
+
+% Arc
+n 6826.5 4348.5 148.5 -90.6 0.6 arc
+gs col0 s gr
+
+% Arc
+n 4873.0 5477.0 148.0 89.2 -179.2 arc
+gs col0 s gr
+
+% Arc
+n 4873.0 5027.0 148.0 89.2 -179.2 arc
+gs col0 s gr
+
+% Arc
+n 4873.0 4577.0 148.0 89.2 -179.2 arc
+gs col0 s gr
+
+% Arc
+n 6827.0 5027.0 148.0 -0.8 90.8 arc
+gs col0 s gr
+
+% Arc
+n 6827.0 5477.0 148.0 -0.8 90.8 arc
+gs col0 s gr
+
+% Arc
+n 6827.0 4577.0 148.0 -0.8 90.8 arc
+gs col0 s gr
+
+% Polyline
+7.500 slw
+n 3896 5400 m 3904 5400 l gs col0 s gr
+% Polyline
+15.000 slw
+n 3900 4200 m
+ 7350 4200 l gs col0 s gr 
+% Polyline
+7.500 slw
+n 4050 5250 m 4200 5250 l 4125 5100 l
+ cp gs -0.00 setgray ef gr gs col0 s gr 
+% Polyline
+n 4425 4125 m 4425 4275 l 4575 4200 l
+ cp gs -0.00 setgray ef gr gs col0 s gr 
+% Polyline
+n 5130 5025 m 5025 5025 5025 5220 105 arcto 4 {pop} repeat
+  5025 5325 6570 5325 105 arcto 4 {pop} repeat
+  6675 5325 6675 5130 105 arcto 4 {pop} repeat
+  6675 5025 5130 5025 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+15.000 slw
+n 5025 5625 m
+ 4875 5625 l gs col0 s gr 
+% Polyline
+n 4875 5175 m
+ 5025 5175 l gs col0 s gr 
+% Polyline
+n 5025 4725 m
+ 4875 4725 l gs col0 s gr 
+% Polyline
+n 6975 4350 m
+ 6975 5475 l gs col0 s gr 
+% Polyline
+n 6825 5175 m
+ 6675 5175 l gs col0 s gr 
+% Polyline
+n 6675 4725 m
+ 6825 4725 l gs col0 s gr 
+% Polyline
+n 6825 5625 m
+ 6675 5625 l gs col0 s gr 
+% Polyline
+n 4725 4350 m
+ 4725 5475 l gs col0 s gr 
+% Polyline
+7.500 slw
+n 4650 4500 m 4800 4500 l 4725 4350 l
+ cp gs -0.00 setgray ef gr gs col0 s gr 
+% Polyline
+n 7050 4350 m 6900 4350 l 6975 4500 l
+ cp gs -0.00 setgray ef gr gs col0 s gr 
+% Polyline
+n 7125 4125 m 7125 4275 l 7275 4200 l
+ cp gs -0.00 setgray ef gr gs col0 s gr 
+% Polyline
+n 2205 5250 m 2100 5250 2100 5445 105 arcto 4 {pop} repeat
+  2100 5550 3795 5550 105 arcto 4 {pop} repeat
+  3900 5550 3900 5355 105 arcto 4 {pop} repeat
+  3900 5250 2205 5250 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+n 2580 4725 m 2475 4725 2475 4920 105 arcto 4 {pop} repeat
+  2475 5025 4170 5025 105 arcto 4 {pop} repeat
+  4275 5025 4275 4830 105 arcto 4 {pop} repeat
+  4275 4725 2580 4725 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+n 2205 4050 m 2100 4050 2100 4245 105 arcto 4 {pop} repeat
+  2100 4350 3795 4350 105 arcto 4 {pop} repeat
+  3900 4350 3900 4155 105 arcto 4 {pop} repeat
+  3900 4050 2205 4050 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+n 5130 4575 m 5025 4575 5025 4770 105 arcto 4 {pop} repeat
+  5025 4875 6570 4875 105 arcto 4 {pop} repeat
+  6675 4875 6675 4680 105 arcto 4 {pop} repeat
+  6675 4575 5130 4575 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+n 5130 5475 m 5025 5475 5025 5670 105 arcto 4 {pop} repeat
+  5025 5775 6570 5775 105 arcto 4 {pop} repeat
+  6675 5775 6675 5580 105 arcto 4 {pop} repeat
+  6675 5475 5130 5475 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+% Polyline
+n 7455 4050 m 7350 4050 7350 4245 105 arcto 4 {pop} repeat
+  7350 4350 8595 4350 105 arcto 4 {pop} repeat
+  8700 4350 8700 4155 105 arcto 4 {pop} repeat
+  8700 4050 7455 4050 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+$F2psEnd
+rs
diff --git a/doc/charm++/fig/pup.fig b/doc/charm++/fig/pup.fig
new file mode 100644 (file)
index 0000000..5987df4
--- /dev/null
@@ -0,0 +1,82 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 4873.532 4348.000 4725 4350 4768 4244 4875 4200
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 6826.468 4348.532 6825 4200 6931 4243 6975 4350
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 4873.000 5477.000 4875 5625 4769 5582 4725 5475
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 4873.000 5027.000 4875 5175 4769 5132 4725 5025
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 4873.000 4577.000 4875 4725 4769 4682 4725 4575
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 6827.000 5027.000 6975 5025 6932 5131 6825 5175
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 6827.000 5477.000 6975 5475 6932 5581 6825 5625
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 6827.000 4577.000 6975 4575 6932 4681 6825 4725
+6 3825 4950 4200 5475
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 3977.000 5252.000 4125 5250 4082 5356 3975 5400
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        4125 5025 4125 5250
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        3975 5400 3900 5400
+-6
+6 4050 4125 4350 4800
+5 1 0 2 0 7 50 0 -1 0.000 0 0 0 0 4273.532 4348.000 4125 4350 4168 4244 4275 4200
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        4125 4350 4125 4725
+-6
+6 2167 4106 8542 5756
+4 1 0 50 0 18 12 0.0000 4 180 1020 5842 5231 p.isSizing()\001
+4 1 0 50 0 18 12 0.0000 4 180 1440 2992 5456 Pup Constructor\001
+4 1 0 50 0 18 12 0.0000 4 180 1410 3367 4931 p.isUnpacking()\001
+4 1 0 50 0 18 12 0.0000 4 135 1530 2992 4256 User Constructor\001
+4 1 0 50 0 18 12 0.0000 4 135 1245 5842 4781 User Methods\001
+4 1 0 50 0 18 12 0.0000 4 180 1185 5857 5681 p.isPacking()\001
+4 1 0 50 0 18 12 0.0000 4 135 960 8017 4256 Destructor\001
+-6
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 1
+        3900 5400
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        3900 4200 7350 4200
+2 3 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 4
+        4050 5250 4200 5250 4125 5100 4050 5250
+2 3 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 4
+        4425 4125 4425 4275 4575 4200 4425 4125
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        6675 5325 6675 5025 5025 5025 5025 5325 6675 5325
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        5025 5625 4875 5625
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        4875 5175 5025 5175
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        5025 4725 4875 4725
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        6975 4350 6975 5475
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        6825 5175 6675 5175
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        6675 4725 6825 4725
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        6825 5625 6675 5625
+2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2
+        4725 4350 4725 5475
+2 3 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 4
+        4650 4500 4800 4500 4725 4350 4650 4500
+2 3 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 4
+        7050 4350 6900 4350 6975 4500 7050 4350
+2 3 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 4
+        7125 4125 7125 4275 7275 4200 7125 4125
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        3900 5550 3900 5250 2100 5250 2100 5550 3900 5550
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        4275 5025 4275 4725 2475 4725 2475 5025 4275 5025
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        3900 4350 3900 4050 2100 4050 2100 4350 3900 4350
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        6675 4875 6675 4575 5025 4575 5025 4875 6675 4875
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        6675 5775 6675 5475 5025 5475 5025 5775 6675 5775
+2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+        8700 4350 8700 4050 7350 4050 7350 4350 8700 4350
diff --git a/doc/charm++/fig/pup.png b/doc/charm++/fig/pup.png
new file mode 100644 (file)
index 0000000..859f020
Binary files /dev/null and b/doc/charm++/fig/pup.png differ
index 679b67990871e76e39163a0cfc05c5aca55ee4c4..7a11ee5162bcd1585da1cc7639c1742649e05b7e 100644 (file)
@@ -11,105 +11,95 @@ Like many \CC\ concepts, the PUP framework is easier to use than
 describe: 
 
 \begin{alltt}
-class foo \{
+class foo : public mySuperclass \{
  private:
     double a;
     int x;
     char y;
     unsigned long z;
-    float q[3];
+    float arr[3];
  public:
     ...other methods...
 
     //pack/unpack routine: describe my fields to charm++
     void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
       p|a;
       p|x; p|y; p|z;
-      p(q,3);
+      PUParray(p,arr,3);
     \}
 \};
 \end{alltt}
 
-This class's pup routine describes the fields of a \uw{foo} to \charmpp\.
-This will allow \charmpp\ to: marshall parameters of type \uw{foo},
-send \uw{foo} objects in messages, translate \uw{foo}s across processors,
-inspect and modify \uw{foo} objects in the debugger, and checkpoint 
-calculations involving \uw{foo}s.
+This class's pup routine describes the fields of a \uw{foo} to \charmpp{}.
+This allows \charmpp\ to: marshall parameters of type \uw{foo} across processors,
+translate \uw{foo}s across processor architectures, read and write \uw{foo}s
+to disk files, inspect and modify \uw{foo} objects in the debugger, and 
+checkpoint and restart calculations involving \uw{foo}s.
 
-As shown, you describe foo's contents by writing a routine called ``pup''
-which passes the parts of foo to an object of type 
-\index{PUP::er} \kw{PUP::er}.  You can apply a \kw{PUP::er} to any 
-primitive variable or any variable with a pup routine using ``p|a;''.
-For an array of primitive variables, you apply the array and an integer
-that gives the length of the array, as in ``p(q,3);''.  You can pass a 
-simple run of bytes 
-by calling the \kw{PUP::er} with a ``void *'' and number of bytes
-Sending data as bytes, however, prevents cross-platform operation,
-and should be avoided if possible.
 
 
 \subsubsection{PUP contract}
-\label{sec:pupmodes}
 
-\charmpp{} uses your pup routine to both pack and unpack, 
-by passing different types of \kw{PUP::er}s to it.  The routine
-\kw{p.isUnpacking()} returns true if your object is being unpacked---that 
-is, your object is being filled with values.  Your pup routine must
-properly save and restore data in both saving and unpacking modes.
-
-Simple data types, and objects with their own
-\kw{PUP::er} methods, can be handled directly using the ``p|a''
-syntax.  Complex types, particularly dynamically allocated data types,
-usually require special attention. Typically this only requires
-a \kw{p.isUnpacking()} conditional block, where you perform the 
-appropriate allocation.  See Section~\ref{sec:pupdynalloc} for more
-information and examples.   
-
-There are three separate types of \kw{PUP::er}: sizing, which 
-only computes the size of your data without modifying it;
-packing, which reads values out of your data; and unpacking,
-which writes values into your data.  You can determine
-exactly which type of \kw{PUP::er} was passed to you using the
-\kw{p.isSizing()}, \kw{p.isPacking()}, and \kw{p.isUnpacking()}
-routines, however, sizing and packing should almost always be 
-handled identically, so most programs should use \kw{p.isUnpacking()}
-and \kw{!p.isUnpacking()}.  Any program that calls \kw{p.isPacking()} 
-and does not also call \kw{p.isSizing()} is probably a bug; because
-sizing and packing must see the same data.
+Your object's pup routine must save and restore all your object's data.
+As shown, you save and restore a class's contents by writing a routine c
+alled ``pup'' which passes all the parts of the class to an object of type 
+\index{PUP::er} \kw{PUP::er}, which does the saving or restoring.  
+We often use ``pup'' as a verb, meaning ``to save/restore the value of''
+or equivalently, ``to call the pup routine of''.
 
-The \kw{p.isDeleting()} flag indicates the object will be deleted
-after calling the pup routine.  This is normally only needed for
-pup routines called via the C or f90 interface, as provided by 
-AMPI or the FEM framework.  Other \charmpp{} array elements, 
-marshalled parameters, and other C++ interface objects 
-have their destructor called when they are deleted, so the 
-\kw{p.isDeleting()} call is not normally required.
+Pup routines for complicated objects normally call the pup routines
+for their simpler parts.  Since all objects depend on their immediate
+superclass, the first line of every pup routine is a call to the 
+superclass's pup routine---the only time you shouldn't call your superclass's
+pup routine is when you don't have a superclass.  If your superclass has
+no pup routine, you must pup the values in the superclass yourself.
 
 
-\paragraph{PUP operator |}
+\paragraph{PUP operator}
 \label{sec:pupstl}
 
-The recommended way to pup an object a is to simply call ``p|a''.
+The recommended way to pup any object \verb.a. is to use \verb.p|a;..
+This syntax is an operator \verb.|. applied to the \kw{PUP::er} \verb.p.
+and the user variable \verb.a..
 
-The ``p|a'' syntax works wherever a is:
+The \verb.p|a;. syntax works wherever a is:
 
 \begin{itemize}
  \item A simple type, including char, short, int, long, float, or double.
-    In this case, ``p|a'' is equivalent to ``p(a)''.  
- \item An object with a pup routine.
-    In this case, ``p|a'' is equivalent to ``a.pup(p)''.  
+    In this case, \verb.p|a;. copies the data in-place.
+    This is equivalent to passing the type directly to the \kw{PUP::er}   
+       using \verb.p(a)..
+ \item Any object with a pup routine.
+    In this case, \verb.p|a;. calls the object's pup routine.
+    This is equivalent to the statement \kw{a.pup(p);}. 
  \item A pointer to a PUP::able object, as described in Section~\ref{sec:pup::able}.
+    In this case, \verb.p|a;. allocates and copies the appropriate subclass.
  \item An object with a \kw{PUPbytes}(\uw{myClass}) declaration in the header.
- \item An object with a custom \kw{operator |} defined.
+    In this case, \verb.p|a;. copies the object as plain bytes, like memcpy.
+ \item An object with a custom \verb.operator |. defined.
+    In this case, \verb.p|a;. calls the custom \verb.operator |..
 \end{itemize}
 
-If the variable a is from the C++ Standard Template Library, you can include 
-operator\verb.|.'s for the STL types vector, map, list, pair, and string 
-by including the header ``pup\_stl.h''.
+For container types, you must simply pup each element of the container.
+For arrays, you can use the utility routine \kw{PUParray}, which takes
+the \kw{PUP::er}, the array base pointer, and the array length.
+This utility routine is defined for user-defined types T as:
+  \begin{alltt}
+    template<class T>
+    inline void PUParray(PUP::er &p,T *array,int length) \{
+       for (int i=0;i<length;i++) p|array[i];
+    \}
+  \end{alltt}
+
+If the variable is from the C++ Standard Template Library, you can include 
+operator\verb.|.'s for STL vector, map, list, pair, and string, templated
+on anything, by including the header ``pup\_stl.h''.
 
-If the object does not have a pup routine, but can be packed as raw bytes,
-add the macro \kw{PUPbytes}(\uw{myClass}) in the header.  This will define
-an operator\verb.|. to pup the class as sizeof(myClass) raw bytes.
+As usual in \CC{}, pointers and allocatable objects usually require special handling. 
+Typically this only requires a \kw{p.isUnpacking()} conditional block, 
+where you perform the appropriate allocation.  See 
+Section~\ref{sec:pupdynalloc} for more information and examples.  
 
 If the object does not have a pup routine, and you cannot add one or use 
 PUPbytes, you can define an operator\verb.|. to pup the object.
@@ -123,20 +113,49 @@ operator\verb.|. might look like:
   \}
 \end{alltt}
 
+
+\paragraph{PUP as bytes}
+\label{sec:pupbytes}
+
+For classes and structs with many fields, it can be tedious and 
+error-prone to list all the fields in the pup routine.
+You can avoid this listing in two ways, as long as the
+object can be safely copied as raw bytes---this is normally 
+the case for simple structs and classes without pointers.
+
+\begin{itemize}
+\item Use the \verb.PUPbytes(myClass). macro in your header file.
+      This lets you use the \verb.p|*myPtr;. syntax 
+      to pup the entire class as sizeof(myClass) raw bytes.
+
+\item Use \verb.p((void *)myPtr,sizeof(myClass));. in the pup 
+      routine.  This is a direct call to pup a set of bytes.
+\end{itemize}
+
+Note that pupping as bytes is just like using `memcpy': 
+it does nothing to the data but copy it whole.
+For example, if the class contains any pointers, you
+must make sure to do any allocation needed, and
+pup the referenced data yourself.
+
+Pupping as bytes will prevent your pup routine from 
+ever being able to work across different machine 
+architectures.  We don't do this very often yet, but 
+eventually may, so pupping as bytes is currently discouraged.
+
+
+
 \paragraph{PUP overhead}
 \label{sec:pupoverhead}
 
-Note that the same data must be passed to the \kw{PUP::er} in the same
-order regardless of the pack direction.  This is the fundamental
-beauty of the \kw{PUP::er} framework.
-
-The \kw{PUP::er} overhead is very small-- one virtual function call
+The \kw{PUP::er} overhead is very small---one virtual function call
 for each item or array to be packed/unpacked.  The actual packing/unpacking is
 normally a simple memory-to-memory binary copy. 
 
-The pup syntax ``p\verb.|.a'' normally results in a call to a's pup routine. 
-Note that this syntax is also used by parameter marshalling and copying readonly
-variables.
+For arrays of builtin types like ``int" and ``double", or arrays of a type 
+with the ``PUPbytes'' declaration, \kw{PUParray} uses an even faster block 
+transfer, with one virtual function call per array.
+
 
 \paragraph{PUP structured dagger}
 \label{sec:pupsdag}
@@ -158,36 +177,76 @@ class bar : public barParent \{
 \end{alltt}
 
 
-\subsubsection{C and Fortran bindings}
-C and Fortran programmers can use a limited subset of the
-\kw{PUP::er} capability.  The routines all take a 
-handle named \kw{pup\_er}.  The routines 
-have the prototype:
-\begin{alltt}
-void pup\_\kw{type}(pup\_er p,\kw{type} *val);
-void pup\_\kw{type}s(pup\_er p,\kw{type} *vals,int nVals);
-\end{alltt}
-The first call is for use with a single element;
-the second call is for use with an array.
-The supported types are char, short, int, long,
-uchar, ushort, uint, ulong, float, and double,
-which all have the usual C meanings.
 
-A byte-packing routine
-\begin{alltt}
-void pup\_bytes(pup\_er p,void *data,int nBytes);
-\end{alltt}
-is also provided, but its use is discouraged
-for cross-platform puping.
+\paragraph{PUP modes}
+\label{sec:pupmodes}
 
-\kw{pup\_isSizing}, \kw{pup\_isPacking}, \kw{pup\_isUnpacking},
-and \kw{pup\_isDeleting} calls are also available.
-Since C and Fortran have no destructors, you should 
-actually deallocate all data when passed a deleting \kw{pup\_er}.
+\charmpp{} uses your pup routine to both pack and unpack, 
+by passing different types of \kw{PUP::er}s to it.  The routine
+\kw{p.isUnpacking()} returns true if your object is being unpacked---that 
+is, your object's values are being restored.  Your pup routine must
+work properly in sizing, packing, and unpacking modes; and
+to save and restore properly, the same fields must be passed 
+to the \kw{PUP::er}, in the exact same order, in all modes.
+This means most pup routines can ignore the pup mode.
+
+Three modes are used, with three separate types of \kw{PUP::er}: 
+sizing, which only computes the size of your data without modifying it;
+packing, which reads/saves values out of your data; and unpacking,
+which writes/restores values into your data.  You can determine
+exactly which type of \kw{PUP::er} was passed to you using the
+\kw{p.isSizing()}, \kw{p.isPacking()}, and \kw{p.isUnpacking()}
+routines. However, sizing and packing should almost always be 
+handled identically, so most programs should use \kw{p.isUnpacking()}
+and \kw{!p.isUnpacking()}.  Any program that calls \kw{p.isPacking()} 
+and does not also call \kw{p.isSizing()} is probably buggy, because
+sizing and packing must see exactly the same data.
+
+
+The \kw{p.isDeleting()} flag indicates the object will be deleted
+after calling the pup routine.  This is normally only needed for
+pup routines called via the C or f90 interface, as provided by 
+AMPI or the FEM framework.  Other \charmpp{} array elements, 
+marshalled parameters, and other C++ interface objects 
+have their destructor called when they are deleted, so the 
+\kw{p.isDeleting()} call is not normally required---instead,
+memory should be deallocated in the destructor as usual.
+
+
+\subsubsection{Life Cycle}
+\label{sec:lifecycle}
+
+\begin{figure}[h]
+\begin{center}
+\includegraphics[width=6.0in]{fig/pup}
+\end{center}
+\caption{Life cycle of an object with a pup routine.}
+\label{fig:pup}
+\end{figure}
+
+The life cycle of an object with a pup routine is shown in 
+Figure~\ref{fig:pup}.  As usual in \CC{}, objects are 
+constructed, do some processing, and are then destroyed.
+
+Objects can be created in one of two ways: they can
+be created using a normal constructor as usual; or they
+can be created using their pup constructor.  The pup constructor
+for \charmpp{} array elements and \kw{PUP::able} objects
+is a ``migration constructor'' that takes a single ``CkMigrateMessage *";
+for other objects, such as parameter marshalled objects,
+the pup constructor has no parameters.  The pup constructor
+is always followed by a call to the object's pup routine in
+\verb.isUnpacking. mode.
+
+Once objects are created, they respond to regular user methods
+and remote entry methods as usual.  At any time, the object 
+pup routine can be called in \verb.isSizing. or \verb.isPacking.
+mode.  User methods and sizing or packing pup routines can be called
+repeatedly over the object lifetime.
+
+Finally, objects are destroyed by calling their destructor
+as usual.
 
-C and Fortran users cannot use \kw{PUP::able} objects, 
-seeking, or write custom \kw{PUP::er}s. Using the \CC\
-interface is recommended.
 
 
 \subsubsection{Dynamic Allocation}
@@ -197,33 +256,197 @@ If your class has fields that are dynamically allocated, when unpacking
 these need to be allocated (in the usual way) before you pup them.
 Deallocation should be left to the class destructor as usual.
 
+\paragraph{No allocation}
+The simplest case is when there is no dynamic allocation.
+\begin{alltt}
+class keepsFoo : public mySuperclass \{
+private:
+    foo f; /* simple foo object*/
+public:
+    keepsFoo(void) \{ \}
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      p|f; // pup f's fields (calls f.pup(p);) 
+    \}
+    ~keepsFoo() \{ \}
+\};
+\end{alltt}
+
+\paragraph{Allocation outside pup}
+The next simplest case is when we contain a class 
+that is always allocated during our constructor,
+and deallocated during our destructor.  Then no allocation
+is needed within the pup routine.
+\begin{alltt}
+class keepsHeapFoo : public mySuperclass \{
+private:
+    foo *f; /*Heap-allocated foo object*/
+public:
+    keepsHeapFoo(void) \{
+      f=new foo;
+    \}
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      p|*f; // pup f's fields (calls f->pup(p))
+    \}
+    ~keepsHeapFoo() \{delete f;\}
+\};
+\end{alltt}
+
+\paragraph{Allocation during pup}
+If we need values obtained during the pup routine
+before we can allocate the class, we must 
+allocate the class inside the pup routine.
+Be sure to protect the allocation with ``if (p.isUnpacking())''.
 \begin{alltt}
-class bar \{
+class keepsOneFoo : public mySuperclass \{
 private:
     foo *f; /*Heap-allocated foo object*/
+public:
+    keepsOneFoo(...) \{f=new foo(...);\}
+    keepsOneFoo() \{f=NULL;\} /* pup constructor */
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      ...
+      if (p.isUnpacking()) /* must allocate foo now */
+         f=new foo(...);
+      p|*f;//pup f's fields
+    \}
+    ~keepsOneFoo() \{delete f;\}
+\};
+\end{alltt}
+
+\paragraph{Allocatable array}
+For example, if we keep an array of doubles,
+we need to know how many doubles there are 
+before we can allocate the array.  Hence we must
+first pup the array length, do our allocation,
+and then pup the array data.  We could allocate memory using 
+malloc/free or other allocators in exactly the same way.
+\begin{alltt}
+class keepsDoubles : public mySuperclass \{
+private:
     int n;
-    double *arr;/*malloc'd array of n doubles*/
+    double *arr;/*new'd array of n doubles*/
 public:
-    ...other methods...
-    //Destructor is the usual
-    ~bar() \{free(arr);delete f;\}
+    keepsDoubles(int n_) \{
+      n=n_;
+      arr=new double[n];
+    \}
+    keepsDoubles() \{ \} 
     
-    //pack/unpack: describe my fields to Charm++
     void pup(PUP::er &p) \{
-      if (p.isUnpacking()) 
-         f=new foo;
-      f->pup(p);//pup f's fields
-      
+      mySuperclass::pup(p);
       p|n;//pup the array length n
-      if (p.isUnpacking()) 
-         arr=(double *)malloc(sizeof(double)*n);
-      p(arr,n);//pup array data
+      if (p.isUnpacking())  arr=new double[n];
+      PUParray(p,arr,n); //pup data in the array
     \}
+    
+    ~keepsDoubles() \{delete[] arr;\}
 \};
 \end{alltt}
 
+\paragraph{NULL object pointer}
+If our allocated object may be NULL, our allocation
+becomes much more complicated.  We must first check
+and pup a flag to indicate whether the object exists, 
+then depending on the flag, pup the object.
+\begin{alltt}
+class keepsNullFoo : public mySuperclass \{
+private:
+    foo *f; /*Heap-allocated foo object, or NULL*/
+public:
+    keepsNullFoo(...) \{ if (...) f=new foo(...);\}
+    keepsNullFoo() \{f=NULL;\}
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      int has_f=(f!=NULL);
+      p|has_f;
+      if (has_f) {
+        if (p.isUnpacking()) f=new foo;
+        p|*f;
+      } else {
+        f=NULL;
+      }
+    \}
+    ~keepsNullFoo() \{if (f!=NULL) delete f;\}
+\};
+\end{alltt}
+
+This sort of code is normally much longer and more
+error-prone if split into the various packing/unpacking cases.
+
+\paragraph{Array of classes}
+An array of actual classes can be treated exactly the same way
+as an array of basic types.  PUParray will pup each 
+element of the array properly, calling the appropriate \verb.operator|..
+\begin{alltt}
+class keepsFoos : public mySuperclass \{
+private:
+    int n;
+    foo *arr;/*new'd array of n foos*/
+public:
+    keepsFoos(int n_) \{
+      n=n_;
+      arr=new foo[n];
+    \}
+    keepsFoos() \{ arr=NULL; \} 
+    
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      p|n;//pup the array length n
+      if (p.isUnpacking())  arr=new foo[n];
+      PUParray(p,arr,n); //pup each foo in the array
+    \}
+    
+    ~keepsFoos() \{delete[] arr;\}
+\};
+\end{alltt}
 
-\subsubsection{Automatic allocation via PUP::able}
+
+\paragraph{Array of pointers to classes}
+An array of pointers to classes must handle each element
+separately, since the PUParray routine does not work with 
+pointers.  An ``allocate'' routine to set up the array
+could simplify this code.  More ambitious is to construct
+a ``smart pointer'' class that includes a pup routine.
+\begin{alltt}
+class keepsFooPtrs : public mySuperclass \{
+private:
+    int n;
+    foo **arr;/*new'd array of n pointer-to-foos*/
+public:
+    keepsFooPtrs(int n_) \{
+      n=n_;
+      arr=new foo*[n]; // allocate array
+      for (int i=0;i<n;i++) arr[i]=new foo(...); // allocate i'th foo
+    \}
+    keepsFooPtrs() \{ arr=NULL; \} 
+    
+    void pup(PUP::er &p) \{
+      mySuperclass::pup(p);
+      p|n;//pup the array length n
+      if (p.isUnpacking()) arr=new foo*[n]; // allocate array
+      for (int i=0;i<n;i++) \{
+        if (p.isUnpacking()) arr[i]=new foo(...); // allocate i'th foo
+        p|*arr[i];  //pup the i'th foo
+      \}
+    \}
+    
+    ~keepsFooPtrs() \{
+       for (int i=0;i<n;i++) delete arr[i];
+       delete[] arr;
+     \}
+\};
+\end{alltt}
+
+Note that this will not properly handle the case where
+some elements of the array are actually subclasses of foo,
+with virtual methods.  The PUP::able framework described
+in the next section can be helpful in this case.
+
+
+\subsubsection{Subclass allocation via PUP::able}
 \label{sec:pup::able}
 If the class \uw{foo} above might have been a subclass, instead of
 simply using \uw{new foo} above we would have had to allocate 
@@ -414,6 +637,39 @@ In the example above, we could do:
 \end{alltt}
 
 
+\subsubsection{C and Fortran bindings}
+C and Fortran programmers can use a limited subset of the
+\kw{PUP::er} capability.  The routines all take a 
+handle named \kw{pup\_er}.  The routines 
+have the prototype:
+\begin{alltt}
+void pup\_\kw{type}(pup\_er p,\kw{type} *val);
+void pup\_\kw{type}s(pup\_er p,\kw{type} *vals,int nVals);
+\end{alltt}
+The first call is for use with a single element;
+the second call is for use with an array.
+The supported types are char, short, int, long,
+uchar, ushort, uint, ulong, float, and double,
+which all have the usual C meanings.
+
+A byte-packing routine
+\begin{alltt}
+void pup\_bytes(pup\_er p,void *data,int nBytes);
+\end{alltt}
+is also provided, but its use is discouraged
+for cross-platform puping.
+
+\kw{pup\_isSizing}, \kw{pup\_isPacking}, \kw{pup\_isUnpacking},
+and \kw{pup\_isDeleting} calls are also available.
+Since C and Fortran have no destructors, you should 
+actually deallocate all data when passed a deleting \kw{pup\_er}.
+
+C and Fortran users cannot use \kw{PUP::able} objects, 
+seeking, or write custom \kw{PUP::er}s. Using the \CC\
+interface is recommended.
+
+
+
 \subsubsection{Common PUP::ers}
 The most common \kw{PUP::er}s used are \kw{PUP::sizer},
 \kw{PUP::toMem}, and \kw{PUP::fromMem}.  These are sizing,