00001 00002 #ifndef PUP_CMIALLOC_H__ 00003 #define PUP_CMIALLOC_H__ 00004 00005 #include "pup.h" 00006 #include "converse.h" 00007 00008 #include <stdio.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 #include <ctype.h> 00012 00013 /******** CMIALLOC buffer management functions ******/ 00014 00015 /* Given a user chunk m, extract the enclosing chunk header fields: */ 00016 00017 //Align data sizes to 8 bytes 00018 #define ALIGN8_LONG(x) (intptr_t)((~7)&((x)+7)) 00019 00020 //Assuming Size of CmiChunkHeader is a multiple of 8 bytes!! 00021 00022 /*For CMI alloc'ed memory 00023 CmiAlloc currently has the following memory footprint 00024 00025 |int size|int ref|user allocated buffer| 00026 00027 The ref count can be set so that a sub buffers can be individually 00028 freed. When all sub buffers have been individually freed the 00029 super buffer is freed. This is very use ful for message combining. 00030 00031 For example, the memory foot print of a combined message could 00032 look like this 00033 00034 |size_bigbuf|ref_bigbuf|begin_bigbuf 00035 ..... |size_subbuf1|ref_subbuf1|subbuf1| 00036 .... |size_subbuf2|ref_subbuf2|subbuf2| 00037 ..... |size_subbufk|ref_subbufk|subbufk| 00038 00039 The usr program can then get use each of the sub_bufs 00040 sub_buf1, ... , sub_bufk 00041 00042 These sub_bufs could be converse messages or just data pointers 00043 00044 To create such a combined message, the pup framwork can be used 00045 00046 PUP_cmiAllocSizer psizer; 00047 for(count = 0; count < k; count++) 00048 psizer.pupCmiAllocBuf(&sub_buf[k]); 00049 00050 void *bigbuf = CmiAlloc(psizer.size()); 00051 PUP_toCmiAllocMem pmem(bigbuf); 00052 00053 for(count = 0; count < k; count++) 00054 pmem.pupCmiAllocBuf(&sub_buf[k]); 00055 00056 //NOW big buf has all the subbuffers 00057 //If you also add a converse header to it it can become a 00058 //converse message 00059 00060 //To extract sub buffers from bigbuf 00061 PUP_fromCmiAllocMem pfmem(bigbuf); 00062 00063 //Notice not memory allocation or copying needed on the 00064 //destination 00065 for(count = 0; count < k; count++) 00066 pfmem.pupCmiAllocBuf(&sub_buf[k]); 00067 00068 00069 To free these buffers the user program on the destination after 00070 receiving the messages MUST CALL!! 00071 00072 CmiFree(sub_buf[1]); 00073 .... 00074 CmiFree(sub_buf[k]); 00075 */ 00076 00082 class PUP_cmiAllocSizer : public PUP::sizer { 00083 protected: 00084 //Generic bottleneck: n items of size itemSize 00085 virtual void bytes(void *p,size_t n,size_t itemSize,PUP::dataType t); 00086 public: 00087 //Write data to the given buffer 00088 PUP_cmiAllocSizer(void): PUP::sizer() {} 00089 00090 //Must be a CmiAlloced buf while packing 00091 void pupCmiAllocBuf(void **msg); 00092 00093 //In case source is not CmiAlloced the size can be passed and any 00094 //user buf can be converted into a cmialloc'ed buf 00095 void pupCmiAllocBuf(void **msg, size_t msg_size); 00096 }; 00097 00098 00099 //For packing into a preallocated, presized memory cmialloc'ed buffer 00100 //Can use reference counting to reduce one level of copying on the 00101 //receiver 00102 class PUP_toCmiAllocMem : public PUP::toMem { 00103 protected: 00104 //Generic bottleneck: pack n items of size itemSize from p. 00105 virtual void bytes(void *p,size_t n,size_t itemSize, PUP::dataType t); 00106 00107 public: 00108 //Write data to the given buffer 00109 PUP_toCmiAllocMem(size_t size): PUP::toMem(CmiAlloc(size)) {} 00110 PUP_toCmiAllocMem(void *buf): PUP::toMem(buf) {} 00111 00112 //Copy the size of the buffer and the reference count while packing 00113 //Get the buffer directly from the message while unpacking 00114 //Saves on a copy 00115 void pupCmiAllocBuf(void **msg); 00116 00117 //Non cmialloc'ed buffers can also be passed and pupped as a 00118 //cmialloc'ed buffers 00119 void pupCmiAllocBuf(void **msg, size_t size); 00120 }; 00121 00122 00123 //For unpacking from a memory buffer 00124 class PUP_fromCmiAllocMem : public PUP::fromMem { 00125 protected: 00126 //Generic bottleneck: unpack n items of size itemSize from p. 00127 virtual void bytes(void *p,size_t n,size_t itemSize, PUP::dataType t); 00128 public: 00129 //Read data from the given buffer 00130 //The buffer SHOULD have been CMIALLOC'ed 00131 PUP_fromCmiAllocMem(const void *Nbuf): PUP::fromMem(Nbuf) {} 00132 00133 //Copy the size of the buffer and the reference count while packing 00134 //Get the buffer directly from the message while unpacking 00135 //Saves on a copy 00136 void pupCmiAllocBuf(void **msg); 00137 00138 //size is irrelevant and for consistency with toCmiAllocMem 00139 void pupCmiAllocBuf(void **msg, size_t size) { 00140 pupCmiAllocBuf(msg); 00141 } 00142 }; 00143 00144 #endif