1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
/////////////////////////////////////////////////////////////
// //
// Copyright (c) 2003-2014 by The University of Queensland //
// Centre for Geoscience Computing //
// http://earth.uq.edu.au/centre-geoscience-computing //
// //
// Primary Business: Brisbane, Queensland, Australia //
// Licensed under the Open Software License version 3.0 //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
/////////////////////////////////////////////////////////////
#include "tml/message/packed_message.h"
#include <cstring>
/*!
Constructor. Allocates the buffer and sets the MPI communicator to be used for pack/unpack operations. If the initial buffer size is not given a buffer of initial size 64 is allocated.
\param comm the MPI communicator
\param s the initial size of the buffer
*/
TML_Packed_Message::TML_Packed_Message(MPI_Comm comm,unsigned int s)
{
m_comm=comm;
m_buffersize=s;
m_buffer=new char[m_buffersize];
m_pack_pos=0;
m_unpack_pos=0;
MPI_Pack_size(1,MPI_INT,m_comm,&m_int_increment);
MPI_Pack_size(1,MPI_DOUBLE,m_comm,&m_dbl_increment);
}
/*!
Destructor. Free buffer.
*/
TML_Packed_Message::~TML_Packed_Message()
{
delete [] m_buffer;
}
/*!
Grows the buffer to a given size. If the buffer is already larger that the given size, nothing is done. Used by receiveFrom.
\param size size to which the buffer is grown
*/
void TML_Packed_Message::growTo(int size)
{
if(size>m_buffersize){
char *temp = new char[size];
memcpy((void*)temp,m_buffer,size_t(m_pack_pos));
delete [] m_buffer;
m_buffer = temp;
m_buffersize = size;
}
}
/*!
Grows the buffer to twice its current size, thus guaranteeing that append works in amortized constant time.
*/
void TML_Packed_Message::grow()
{
growTo(2*m_buffersize);
}
/*!
Append an integer to the buffer. If necessary, the buffer is enlarged.
\warning currently does not check if there is enough free space to allocate larger buffer
*/
void TML_Packed_Message::append(int i)
{
while(m_pack_pos+m_int_increment>m_buffersize){ // to small, grow
grow();
}
MPI_Pack(&i,1,MPI_INT,m_buffer,m_buffersize,&m_pack_pos,m_comm);
}
/*!
Append a double to the buffer. If necessary, the buffer is enlarged.
\warning currently does not check if there is enough free space to allocate larger buffer
\sa grow()
*/
void TML_Packed_Message::append(double d)
{
while(m_pack_pos+m_dbl_increment>m_buffersize){ // to small, grow
grow();
}
MPI_Pack(&d,1,MPI_DOUBLE,m_buffer,m_buffersize,&m_pack_pos,m_comm);
}
/*!
Append a STL string to the buffer. The string is internally handeled by packing the length frist and then the string. If necessary, the buffer is enlarged.
\warning currently does not check if there is enough free space to allocate larger buffer
\sa grow()
*/
void TML_Packed_Message::append(const string& str)
{
int len=str.size();
while (m_pack_pos+m_int_increment+len>m_buffersize){
grow();
}
MPI_Pack(&len,1,MPI_INT,m_buffer,m_buffersize,&m_pack_pos,m_comm);
MPI_Pack((void *)str.c_str(),len,MPI_CHAR,m_buffer,m_buffersize,&m_pack_pos,m_comm);
}
/*!
Append a Vec3 to the message buffer. Calls append(double) per element
*/
void TML_Packed_Message::append(const Vec3& v)
{
append(v[0]);
append(v[1]);
append(v[2]);
}
/*!
Append a boolean to the message buffer. The bool gest transported as an int (1/0) because
MPI doesn't have a native boolean type. Therefore calls append(int).
*/
void TML_Packed_Message::append(bool b)
{
int i;
if(b){i=1;}
else {i=0;}
append(i);
}
/*!
Pops an integer from the buffer, i.e. it pops the last sizeof(MPI_INT) bytes of the buffer, interpreting them as an int.
\warning No check for underflow
\return the int.
*/
int TML_Packed_Message::pop_int()
{
int res;
MPI_Unpack(m_buffer,m_buffersize,&m_unpack_pos,&res,1,MPI_INT,m_comm);
return res;
}
/*!
Pops a double from the buffer.
\warning No check for underflow
\return the double.
\sa CMPIBuffer::pop_int()
*/
double TML_Packed_Message::pop_double()
{
double res;
MPI_Unpack(m_buffer,m_buffersize,&m_unpack_pos,&res,1,MPI_DOUBLE,m_comm);
return res;
}
/*!
pop a C-array of doubles from a buffer. Faster than doing multiple pop_double operations
\param dbl the array
\param ndb the number of doubles to be popped
\warning No check for underflow
*/
void TML_Packed_Message::pop_doubles(double *dbl,int ndb)
{
MPI_Unpack(m_buffer,m_buffersize,&m_unpack_pos,dbl,ndb,MPI_DOUBLE,m_comm);
}
/*!
Pops a string from the buffer. The first for bytes are interpreted as int, giving the length of the string (without terminating '\0'), the rest as the characters.
\warning no consistency check, i.e. it is not checked if the length is smaller than the buffersize.
\return the double.
\sa CMPISingle::pop_int()
*/
string TML_Packed_Message::pop_string()
{
int len;
char* res;
MPI_Unpack(m_buffer,m_buffersize,&m_unpack_pos,&len,1,MPI_INT,m_comm);
res=new char[len+1]; // +1 for terminating '\0'
MPI_Unpack(m_buffer,m_buffersize,&m_unpack_pos,res,len,MPI_CHAR,m_comm);
res[len]='\0';
string str=string(res);
delete [] res;
return str;
}
/*!
Pop a Vec3 of the buffer. Calls pop_double per element
*/
Vec3 TML_Packed_Message::pop_vec3()
{
Vec3 res;
res[0]=pop_double();
res[1]=pop_double();
res[2]=pop_double();
return res;
}
/*!
Pop a boolean value of the buffer. Booleans are transported as int (0/1)
*/
bool TML_Packed_Message::pop_bool()
{
bool res;
int i;
i=pop_int();
res=(i==1);
return res;
}
|