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
|
/////////////////////////////////////////////////////////////
// //
// 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 "mpibuf.h"
#include <string.h>
AMPIBufferPP::AMPIBufferPP(MPI_Comm comm):AMPIBuffer(comm)
{}
void AMPIBuffer::append(const Vec3 & V)
{
append(V.X()) ;
append(V.Y()) ;
append(V.Z()) ;
}
Vec3 AMPIBuffer::pop_vector()
{
double x=pop_double();
double y=pop_double();
double z=pop_double();
return Vec3(x,y,z);
}
/*!
Constructor. Allocates the buffer and sets the MPI communicator to be used for send/receive operations.
\param comm the MPI communicator
\param s the size of the buffer
*/
CMPIBuffer::CMPIBuffer(MPI_Comm comm,int s):AMPIBufferPP(comm)
{
m_buffersize=s;
m_buffer=new char[m_buffersize];
// get increments for int,double
MPI_Pack_size(1,MPI_INT,m_comm,&m_int_increment);
MPI_Pack_size(1,MPI_DOUBLE,m_comm,&m_dbl_increment);
m_position=0;
}
CMPIBuffer::~CMPIBuffer()
{
delete m_buffer;
}
/*!
Sends the contents of the buffer to a given destination.
\param dest the rank of the destination process in the current communicator
\param tag the message tag
\warning It is not checked if the destination actually exists.
*/
void CMPIBuffer::sendTo(int dest,int tag)
{
MPI_Send(m_buffer,m_position,MPI_PACKED,dest,tag,m_comm);
}
/*!
Recieves a message from a given source and stores it in the buffer. It is assumed that the buffer is large enough the take the message. If no source and no tag are given, any message from any source is accepted.
\warning No check if the buffer is big enough
\param src rank of the sender in the current communicator, defaults to MPI_ANY_SOURCE
\param tag the message tag, defaults to MPI_ANY_TAG
*/
void CMPIBuffer::receiveFrom(int src,int tag)
{
MPI_Recv(m_buffer,m_buffersize,MPI_PACKED,src,tag,m_comm,&m_status) ;
m_position=0;
}
/*!
Append an integer to the buffer.
\warning No check for overflow
*/
void CMPIBuffer::append(int i)
{
MPI_Pack(&i,1,MPI_INT,m_buffer,m_buffersize,&m_position,m_comm);
}
/*!
Append a double to the buffer.
\warning No check for overflow
*/
void CMPIBuffer::append(double d)
{
MPI_Pack(&d,1,MPI_DOUBLE,m_buffer,m_buffersize,&m_position,m_comm);
}
/*!
Append a string to the buffer. The string appended is a normal (zero-terminated) C-string, but is internally handeled by packing the length frist and then the string.
\warning No check for overflow
*/
void CMPIBuffer::append(const char* str)
{
int len=strlen(str);
MPI_Pack(&len,1,MPI_INT,m_buffer,m_buffersize,&m_position,m_comm);
MPI_Pack((void *)str,len,MPI_CHAR,m_buffer,m_buffersize,&m_position,m_comm);
}
/*!
Append an integer to the buffer with overflow check. If the buffer is big enough the integer is appended, if not nothing is done.
\return true if the append succeded, false otherwise
*/
bool CMPIBuffer::append_checked(int i)
{
bool res;
if(m_position+m_int_increment<m_buffersize){
MPI_Pack(&i,1,MPI_INT,m_buffer,m_buffersize,&m_position,m_comm);
res=true;
} else {
res=false;
}
return res;
}
/*!
Append a double to the buffer with overflow check.
\sa CMPIBuffer::append_checked(int i)
*/
bool CMPIBuffer::append_checked(double d)
{
bool res;
if(m_position+m_dbl_increment<m_buffersize){
MPI_Pack(&d,1,MPI_DOUBLE,m_buffer,m_buffersize,&m_position,m_comm);
res=true;
} else {
res=false;
}
return res;
}
/*!
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 CMPIBuffer::pop_int()
{
int res;
MPI_Unpack(m_buffer,m_buffersize,&m_position,&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 CMPIBuffer::pop_double()
{
double res;
MPI_Unpack(m_buffer,m_buffersize,&m_position,&res,1,MPI_DOUBLE,m_comm);
return res;
}
/*!
pop an array of doubles from a buffer
*/
void CMPIBuffer::pop_doubles(double *dbl, int ndb)
{
MPI_Unpack(m_buffer,m_buffersize,&m_position,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()
*/
std::string CMPIBuffer::pop_string()
{
int len = 0;
MPI_Unpack(m_buffer,m_buffersize,&m_position,&len,1,MPI_INT,m_comm);
char *res = new char[len+1]; // +1 for terminating '\0'
MPI_Unpack(m_buffer,m_buffersize,&m_position,res,len,MPI_CHAR,m_comm);
res[len]='\0';
std::string poppedString = res;
delete [] res;
return poppedString;
}
|