File: packed_message.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 (221 lines) | stat: -rw-r--r-- 5,777 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
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;
}