coin-Bcp
BCP_buffer.hpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #ifndef _BCP_BUFFER_H
4 #define _BCP_BUFFER_H
5 
6 #include <memory>
7 #include <vector>
8 
9 // This file is fully docified.
10 
11 #include "BCP_error.hpp"
12 #include "BCP_string.hpp"
13 #include "BCP_message_tag.hpp"
14 #include "BCP_message.hpp"
15 #include "BCP_vector.hpp"
16 
39 class BCP_buffer{
40 public:
41  /* The data members are public for efficiency reasons. The message
42  environment's receiving function should be able to directly manipulate
43  these fields. However, making the virtual base class of all message
44  passing environment to be a friend doesn't help... Anyway, access these
45  fields sparingly.<br>
46  THINK: maybe it's not that inefficient to access the fields thru
47  functions... */
73  int _sender;
75  size_t _pos;
77  size_t _max_size;
80  size_t _size;
82  char* _data;
85 public:
86  //=========================================================================
90  inline BCP_message_tag msgtag() const { return _msgtag; }
93  inline int sender() const { return _sender; }
95  inline int size() const { return _size; }
97  inline const char* data() const { return _data; }
99  //=========================================================================
100 
104  inline void set_position(const int pos) throw(BCP_fatal_error) {
105  if (pos < 0 || pos > size())
106  throw BCP_fatal_error("Incorrest buffer position setting.\n");
107  _pos = pos;
108  }
110  inline void set_size(const int s) throw(BCP_fatal_error) {
111  if (s < 0 || s > size())
112  throw BCP_fatal_error("Incorrest buffer position setting.\n");
113  _size = s;
114  }
116  inline void set_msgtag(const BCP_message_tag tag) { _msgtag = tag; }
117 
119  void set_content(const char* data, const size_t size,
121  _sender = sender;
122  _msgtag = msgtag;
123  if (_max_size < size) {
124  delete[] _data;
125  _data = new char[size];
126  _max_size = size;
127  }
128  _pos = 0;
129  _size = size;
130  if (_size)
131  memcpy(_data, data, size * sizeof(char));
132  }
133 
134 
137  _msgtag = buf._msgtag;
138  _sender = buf._sender;
139  _pos = buf._pos;
140  if (_max_size < buf._max_size) {
141  delete[] _data;
142  _data = new char[buf._max_size];
143  _max_size = buf._max_size;
144  }
145  _size = buf._size;
146  if (_size)
147  memcpy(_data, buf._data, _size * sizeof(char));
148  return *this;
149  }
153  inline void make_fit(const int add_size){
154  if (_max_size < _size + add_size) {
155  _max_size = _size + add_size;
156  /* If > 1M then have spare space of 1/16th (~6%) of used space,
157  if <= 1M then have 64K spare space */
158  _max_size += (_max_size > 1<<20) ? (_max_size >> 4) : (1 << 16) ;
159  char *new_data = new char[_max_size];
160  if (_size)
161  memcpy(new_data, _data, _size);
162  delete[] _data;
163  _data = new_data;
164  }
165  }
168  inline void clear(){
170  _size = 0;
171  _pos = 0;
172  _sender = -1;
173  }
174 
177  template <class T> BCP_buffer& pack(const T& value) {
178  make_fit( sizeof(T) );
179  memcpy(_data + _size, &value, sizeof(T));
180  _size += sizeof(T);
181  return *this;
182  }
183 
186  template <class T> BCP_buffer& unpack(T& value){
187 #ifdef PARANOID
188  if (_pos + sizeof(T) > _size)
189  throw BCP_fatal_error("Reading over the end of buffer.\n");
190 #endif
191  memcpy(&value, _data + _pos, sizeof(T));
192  _pos += sizeof(T);
193  return *this;
194  }
195 
197  template <class T> BCP_buffer& pack(const T* const values,
198  const int length){
199  make_fit( sizeof(int) + sizeof(T) * length );
200  memcpy(_data + _size, &length, sizeof(int));
201  _size += sizeof(int);
202  if (length > 0){
203  memcpy(_data + _size, values, sizeof(T) * length);
204  _size += sizeof(T) * length;
205  }
206  return *this;
207  }
208 
222  template <class T> BCP_buffer& unpack(T*& values, int& length,
223  bool allocate = true)
224  throw(BCP_fatal_error) {
225  if (allocate) {
226 #ifdef PARANOID
227  if (_pos + sizeof(int) > _size)
228  throw BCP_fatal_error("Reading over the end of buffer.\n");
229 #endif
230  memcpy(&length, _data + _pos, sizeof(int));
231  _pos += sizeof(int);
232  if (length > 0){
233 #ifdef PARANOID
234  if (_pos + sizeof(T)*length > _size)
235  throw BCP_fatal_error("Reading over the end of buffer.\n");
236 #endif
237  values = new T[length];
238  memcpy(values, _data + _pos, sizeof(T)*length);
239  _pos += sizeof(T) * length;
240  }
241 
242  } else { /* ! allocate */
243 
244  int l;
245 #ifdef PARANOID
246  if (_pos + sizeof(int) > _size)
247  throw BCP_fatal_error("Reading over the end of buffer.\n");
248 #endif
249  memcpy(&l, _data + _pos, sizeof(int));
250  _pos += sizeof(int);
251  if (l != length)
252  throw BCP_fatal_error("BCP_buffer::unpack() : bad array lentgh.\n");
253  if (length > 0){
254 #ifdef PARANOID
255  if (_pos + sizeof(T)*length > _size)
256  throw BCP_fatal_error("Reading over the end of buffer.\n");
257 #endif
258  memcpy(values, _data + _pos, sizeof(T)*length);
259  _pos += sizeof(T) * length;
260  }
261 
262  }
263 
264  return *this;
265  }
266 
268  BCP_buffer& pack(const BCP_string& value){
269  // must define here, 'cos in BCP_message.C we have only templated members
270  int len = value.length();
271  make_fit( sizeof(int) + len );
272  memcpy(_data + _size, &len, sizeof(int));
273  _size += sizeof(int);
274  if (len > 0){
275  memcpy(_data + _size, value.c_str(), len);
276  _size += len;
277  }
278  return *this;
279  }
282  // must define here, 'cos in BCP_message.C we have only templated members
283  int len = value.length();
284  make_fit( sizeof(int) + len );
285  memcpy(_data + _size, &len, sizeof(int));
286  _size += sizeof(int);
287  if (len > 0){
288  memcpy(_data + _size, value.c_str(), len);
289  _size += len;
290  }
291  return *this;
292  }
295  int len;
296  unpack(len);
297  value.assign(_data + _pos, len);
298  _pos += len;
299  return *this;
300  }
301 
302  // packing/unpacking for BCP_vec
304  template <class T> BCP_buffer& pack(const BCP_vec<T>& vec) {
305  int objnum = vec.size();
306  int new_bytes = objnum * sizeof(T);
307  make_fit( sizeof(int) + new_bytes );
308  memcpy(_data + _size, &objnum, sizeof(int));
309  _size += sizeof(int);
310  if (objnum > 0){
311  memcpy(_data + _size, vec.begin(), new_bytes);
312  _size += new_bytes;
313  }
314  return *this;
315  }
316 
318  template <class T> BCP_buffer& pack(const std::vector<T>& vec) {
319  int objnum = vec.size();
320  int new_bytes = objnum * sizeof(T);
321  make_fit( sizeof(int) + new_bytes );
322  memcpy(_data + _size, &objnum, sizeof(int));
323  _size += sizeof(int);
324  if (objnum > 0){
325  memcpy(_data + _size, &vec[0], new_bytes);
326  _size += new_bytes;
327  }
328  return *this;
329  }
330 
332  template <class T> BCP_buffer& unpack(BCP_vec<T>& vec) {
333  int objnum;
334 #ifdef PARANOID
335  if (_pos + sizeof(int) > _size)
336  throw BCP_fatal_error("Reading over the end of buffer.\n");
337 #endif
338  memcpy(&objnum, _data + _pos, sizeof(int));
339  _pos += sizeof(int);
340  vec.clear();
341  if (objnum > 0){
342 #ifdef PARANOID
343  if (_pos + sizeof(T)*objnum > _size)
344  throw BCP_fatal_error("Reading over the end of buffer.\n");
345 #endif
346  vec.reserve(objnum);
347  vec.insert(vec.end(), _data + _pos, objnum);
348  _pos += objnum * sizeof(T);
349  }
350  return *this;
351  }
352 
354  template <class T> BCP_buffer& unpack(std::vector<T>& vec) {
355  int objnum;
356 #ifdef PARANOID
357  if (_pos + sizeof(int) > _size)
358  throw BCP_fatal_error("Reading over the end of buffer.\n");
359 #endif
360  memcpy(&objnum, _data + _pos, sizeof(int));
361  _pos += sizeof(int);
362  vec.clear();
363  if (objnum > 0){
364 #ifdef PARANOID
365  if (_pos + sizeof(T)*objnum > _size)
366  throw BCP_fatal_error("Reading over the end of buffer.\n");
367 #endif
368  vec.insert(vec.end(), objnum, T());
369  memcpy(&vec[0], _data + _pos, objnum * sizeof(T));
370  _pos += objnum * sizeof(T);
371  }
372  return *this;
373  }
374 
382  _max_size(1<<16/*64K*/), _size(0),
383  _data(new char[_max_size]) {}
385  BCP_buffer(const BCP_buffer& buf) :
387  _max_size(0), _size(0), _data(0){
388  operator=(buf);
389  }
393  delete[] _data;
394  }
396 };
397 
398 #endif
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
Used to indicate that there is no message in the buffer of a process.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
BCP_buffer & unpack(std::vector< T > &vec)
Unpack a std::vector from the buffer.
Definition: BCP_buffer.hpp:354
BCP_buffer & pack(const std::vector< T > &vec)
Pack a std::vector into the buffer.
Definition: BCP_buffer.hpp:318
BCP_buffer & pack(const T *const values, const int length)
Pack a C style array of objects of type T.
Definition: BCP_buffer.hpp:197
BCP_buffer & pack(const BCP_string &value)
Pack a BCP_string into the buffer.
Definition: BCP_buffer.hpp:268
void clear()
Delete every entry.
int _sender
The process id of the sender of the last received message.
Definition: BCP_buffer.hpp:73
const char * c_str() const
Definition: BCP_string.hpp:19
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
Definition: BCP_buffer.hpp:93
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
void reserve(const size_t n)
Reallocate the object to make space for n entries.
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
void set_content(const char *data, const size_t size, int sender, BCP_message_tag msgtag)
Set the buffer to be a copy of the given data.
Definition: BCP_buffer.hpp:119
size_t _pos
The next read position in the buffer.
Definition: BCP_buffer.hpp:75
size_t _max_size
The amount of memory allocated for the buffer.
Definition: BCP_buffer.hpp:77
BCP_string & assign(const char *source, const int len)
Definition: BCP_string.hpp:48
BCP_buffer & operator=(const BCP_buffer &buf)
Make an exact replica of the other buffer.
Definition: BCP_buffer.hpp:136
BCP_buffer & unpack(BCP_vec< T > &vec)
Unpack a BCP_vec from the buffer.
Definition: BCP_buffer.hpp:332
int length() const
Definition: BCP_string.hpp:16
void set_msgtag(const BCP_message_tag tag)
Set the message tag on the buffer.
Definition: BCP_buffer.hpp:116
~BCP_buffer()
The desctructor deletes all data members (including freeing the buffer).
Definition: BCP_buffer.hpp:392
char * _data
Pointer to the buffer itself.
Definition: BCP_buffer.hpp:82
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
Definition: BCP_buffer.hpp:90
void insert(iterator position, const void *first, const size_t num)
Insert num entries starting from memory location first into the vector from position pos...
BCP_buffer(const BCP_buffer &buf)
The copy constructor makes an exact replica of the other buffer.
Definition: BCP_buffer.hpp:385
void set_size(const int s)
Cut off the end of the buffer.
Definition: BCP_buffer.hpp:110
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
The class BCP_vec serves the same purpose as the vector class in the standard template library...
Definition: BCP_vector.hpp:24
BCP_buffer & unpack(T *&values, int &length, bool allocate=true)
Unpack an array of objects of type T, where T must be a built-in type (ar at least something that can...
Definition: BCP_buffer.hpp:222
size_t _size
The current size of the message (the first _size bytes of the buffer).
Definition: BCP_buffer.hpp:80
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
void make_fit(const int add_size)
Reallocate the buffer if necessary so that at least add_size number of additional bytes will fit into...
Definition: BCP_buffer.hpp:153
BCP_buffer & pack(const BCP_vec< T > &vec)
Pack a BCP_vec into the buffer.
Definition: BCP_buffer.hpp:304
const char * data() const
Return a const pointer to the data stored in the buffer.
Definition: BCP_buffer.hpp:97
BCP_buffer()
The default constructor creates a buffer of size 16 Kbytes with no message in it. ...
Definition: BCP_buffer.hpp:381
void set_position(const int pos)
Position the read head in the buffer.
Definition: BCP_buffer.hpp:104
BCP_buffer & pack(BCP_string &value)
Pack a BCP_string into the buffer.
Definition: BCP_buffer.hpp:281
BCP_message_tag _msgtag
The message tag of the last received message.
Definition: BCP_buffer.hpp:70
BCP_buffer & unpack(BCP_string &value)
Unpack a BCP_string from the buffer.
Definition: BCP_buffer.hpp:294
int size() const
Return the size of the current message in the buffer.
Definition: BCP_buffer.hpp:95