File: mpibuf.cpp

package info (click to toggle)
esys-particle 2.3.4%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 13,036 kB
  • ctags: 10,805
  • sloc: cpp: 80,009; python: 5,872; makefile: 1,243; sh: 313; perl: 225
file content (205 lines) | stat: -rw-r--r-- 5,423 bytes parent folder | download
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;
}