MIRA
Buffer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_BUFFER_H_
48 #define _MIRA_BUFFER_H_
49 
50 #include <memory>
51 #include <stdexcept>
52 #include <vector>
53 
54 #include <platform/Types.h>
55 
56 #ifndef Q_MOC_RUN
57 #include <boost/type_traits.hpp>
58 #endif
59 
61 #include <serialization/Array.h>
64 
65 namespace mira {
66 
68 
83 template <typename T, typename Alloc = std::allocator<T> >
84 class Buffer
85 {
86  // the is_pod check is too hard here, since user defined constructors
87  // are allowed, as long there is a trivial default constructor,
88  // copy constructor and trivial destructor
89  static_assert(boost::has_trivial_destructor<T>::value,
90  "Can be used with types that have trivial destructor only");
91 #ifndef MIRA_WINDOWS
92  // VC++2010 does not yet support the "Explicitly-defaulted and deleted
93  // special member functions"-syntax, therefore we must skip these checks
94  static_assert(boost::has_trivial_default_constructor<T>::value,
95  "Can be used with types that have a trivial default constructor only");
96  static_assert(boost::has_trivial_copy_constructor<T>::value,
97  "Can be used with types that have a trivial copy constructor only");
98 #endif
99 
100  // TODO: The standard library has renamed all of the above has_trivial_XYZ to
101  // is_trivially_XYZable WITHOUT providing the old versions for
102  // backward compatibility. Therefore, the following code works on
103  // GCC >= 4.8 but fails on previous GCCs versions and MSVC. Therefore,
104  // we prefer to use the boost variants above, which seem to be more
105  // stable than the standard
106  //static_assert(std::is_trivially_destructible<T>::value,
107  // "Can be used with types that have trivial destructor only");
108  //static_assert(std:::is_trivially_default_constructible<T>::value,
109  // "Can be used with types that have a trivial default constructor only");
110  //static_assert(std::is_trivially_copy_constructible<T>::value,
111  // "Can be used with types that have a trivial copy constructor only");
112 
113 
114 public:
115 
116  // some STL conform typedefs
117  typedef T value_type;
118  typedef typename Alloc::pointer pointer;
119  typedef typename Alloc::const_pointer const_pointer;
120  typedef typename Alloc::reference reference;
121  typedef typename Alloc::const_reference const_reference;
122  typedef T* iterator;
123  typedef const T* const_iterator;
124  typedef std::size_t size_type;
125  typedef ptrdiff_t difference_type;
126  typedef Alloc allocator_type;
127 
128 private:
129 
130  void init() {
131  mBuffer = NULL;
132  mReserved = mSize = 0;
133  mBufferCreated = false;
134  mTakenVector = NULL;
135  }
136 
137 public:
138 
140  Buffer() {
141  init();
142  }
143 
144  /*
145  * Create a buffer and allocate memory of size size
146  */
148  init();
149  resize(size);
150  }
151 
157  Buffer(T* carray, size_type size) {
158  mBuffer = carray;
159  mReserved = mSize = size;
160  mBufferCreated = false;
161  mTakenVector = NULL;
162  }
163 
183  Buffer(std::vector<T>&& other)
184  {
185  mTakenVector = new std::vector<T>;
186  mTakenVector->swap(other);
187 
188  mBuffer = &(*mTakenVector)[0];
189  mReserved = mTakenVector->capacity();
190  mSize = mTakenVector->size();
191  mBufferCreated = false;
192  }
193 
196  setBuffer(NULL, 0);
197  }
198 
199 public:
200 
202  Buffer(const Buffer& other) {
203  init();
204  copy(other);
205  }
206 
208  Buffer& operator=(const Buffer& other) {
209  copy(other);
210  return *this;
211  }
212 
214  void copy(const Buffer& other) {
215  resize(other.size());
216  memcpy(mBuffer, other.data(), other.size()*sizeof(T));
217  }
218 
219 public:
220  // Move semantic
221 
223  Buffer(Buffer&& other) noexcept {
224  init();
225  swap(other);
226  }
227 
229  Buffer& operator=(Buffer&& other) noexcept {
230  swap(other);
231  return *this;
232  }
233 
235  void swap(Buffer& other) {
236  std::swap(mBuffer, other.mBuffer);
237  std::swap(mSize, other.mSize);
238  std::swap(mReserved, other.mReserved);
239  std::swap(mBufferCreated, other.mBufferCreated);
240  std::swap(mTakenVector, other.mTakenVector);
241  }
242 
243 public:
244 
246  bool operator==(const Buffer& other) const {
247  if(size()!=other.size())
248  return false;
249  assert(sizeInBytes()==other.sizeInBytes());
250  return memcmp(data(), other.data(), sizeInBytes()) == 0;
251  }
252 
254  bool operator!=(const Buffer& other) const {
255  return !operator==(other);
256  }
257 
258 public:
259 
264  iterator begin() { return mBuffer; }
265 
270  const_iterator begin() const { return mBuffer; }
271 
276  iterator end() { return mBuffer+mSize; } // also works if empty
277 
282  const_iterator end() const { return mBuffer+mSize; }
283 
284 public:
288  size_type max_size () const { return mAllocator.max_size(); }
289 
293  size_type size() const { return mSize; }
294 
298  size_type sizeInBytes() const { return mSize * sizeof(T); }
299 
303  bool empty () const { return mSize==0; }
304 
309  size_type capacity () const { return mReserved; }
310 
315 
316 public:
317 
324  {
325  if(reserve > mReserved)
326  {
327  std::size_t newSize = mReserved;
328  if(newSize==0)
329  newSize=1;
330  while(reserve > newSize)
331  newSize *= 2;
332 
333  T* newBuffer = mAllocator.allocate(newSize);
334  if(mBuffer!=NULL)
335  memcpy(newBuffer, mBuffer, mSize*sizeof(T));
336  setBuffer(newBuffer, newSize);
337  mBufferCreated = true;
338  }
339  }
340 
341 public:
342 
351  {
352  reserve(size); // make sure buffer is big enough
353  mSize = size;
354  }
355 
356 public:
357 
362  void push_back(const T& x) {
363  resize(mSize+1);
364  mBuffer[mSize-1] = x;
365  }
366 
373  }
374 
379  void push_back(const Buffer<T>& data) {
380  size_type oldSize = mSize;
381  resize(mSize + data.size());
382  memcpy(mBuffer+oldSize*sizeof(T), data.data(), data.sizeInBytes());
383  }
384 
390  void pop_back() {
391  pop_back(1);
392  }
393 
399  void pop_back(size_type elements) {
400  if (elements >= mSize)
401  {
402  this->clear();
403  return;
404  }
405  resize(mSize-elements);
406  }
407 
412  void pop_front() {
413  pop_front(1);
414  }
415 
420  void pop_front(size_type elements) {
421  if (elements >= mSize)
422  {
423  clear();
424  return;
425  }
426  // Move the memory
427  if (elements > 0)
428  {
429  memmove(mBuffer, mBuffer+elements*sizeof(T), (mSize-elements)*sizeof(T));
430  resize(mSize-elements);
431  }
432  }
433 
437  void clear() {
438  mSize = 0;
439  }
440 
441 public:
442 
447  assert(n<mSize);
448  return mBuffer[n];
449  }
450 
455  assert(n<mSize);
456  return mBuffer[n];
457  }
458 
465  rangeCheck(n);
466  return mBuffer[n];
467  }
468 
475  rangeCheck(n);
476  return mBuffer[n];
477  }
478 
483  assert(mSize>0);
484  return mBuffer[0];
485  }
486 
491  assert(mSize>0);
492  return mBuffer[0];
493  }
494 
499  assert(mSize>0);
500  return mBuffer[size()-1];
501  }
502 
507  assert(mSize>0);
508  return mBuffer[size()-1];
509  }
510 
514  pointer data() { return mBuffer; }
515 
519  const_pointer data() const { return mBuffer; }
520 
521 protected:
522 
524  void rangeCheck(size_type n) const
525  {
526  if (n >= size())
527  throw std::out_of_range("Buffer::range_check");
528  }
530 
531 private:
532 
534  void setBuffer(T* newBuffer, size_type size)
535  {
536  // delete old buffer, if any
537  if(mBufferCreated)
538  mAllocator.deallocate(mBuffer,mReserved);
539 
540  // data might have come from a taken over vector, which now is no longer needed
541  delete mTakenVector;
542  mTakenVector = NULL;
543 
544  mBuffer = newBuffer;
545  mReserved = size;
546  }
548 
549 protected:
550 
551  T* mBuffer;
555 
556  Alloc mAllocator;
557 
558  std::vector<T>* mTakenVector;
559 };
560 
562 
564 template<typename Reflector, typename T, typename Allocator>
565 void reflectRead(Reflector& r, Buffer<T, Allocator>& c)
566 {
567  // store the size first
568  uint32 count = c.size();
569  {
571  MIRA_REFLECT_CALL(Reflector, r, "Buffer ReflectCollectionCount",
573  }
574  // store the elements as array
575  serialization::PlainArray<T> array(c.data(), c.size());
576  r.delegate(array);
577 }
578 
580 template<typename Reflector, typename T, typename Allocator>
581 void reflectWrite(Reflector& r, Buffer<T, Allocator>& c)
582 {
583  // restore the size first
584  uint32 count;
585  {
587  MIRA_REFLECT_CALL(Reflector, r, "Buffer ReflectCollectionCount",
589  }
590  // reserve the space and create the elements
591  c.resize(count);
592  // restore the elements as array
593  serialization::PlainArray<T> array(c.data(), c.size());
594  r.delegate(array);
595 }
596 
598 template<typename Reflector, typename T, typename Allocator>
599 void reflect(Reflector& r, Buffer<T, Allocator>& c)
600 {
601  splitReflect(r, c);
602 }
603 
604 template<typename T, typename Allocator>
605 class IsObjectTrackable<Buffer<T, Allocator>> : public std::false_type {};
606 
607 template<typename T, typename Allocator>
608 class IsCollection<Buffer<T, Allocator>> : public std::true_type {};
609 
611 
612 }
613 
614 #endif
Type trait that indicates whether pointer tracking can be enabled for this type.
Definition: IsObjectTrackable.h:68
void reflectWrite(Reflector &r, Buffer< T, Allocator > &c)
Specialization of the non-intrusive reflect for Buffer.
Definition: Buffer.h:581
Alloc::const_pointer const_pointer
Definition: Buffer.h:119
reference back()
Returns a reference to the last element in the vector container.
Definition: Buffer.h:498
Typedefs for OS independent basic data types.
bool operator!=(const Buffer &other) const
Checks for inequality with other buffer.
Definition: Buffer.h:254
bool operator==(const Buffer &other) const
Checks for equality with other buffer.
Definition: Buffer.h:246
Macros for use with reflectors.
void pop_back()
Removes the last element in the vector, effectively reducing the vector size by one.
Definition: Buffer.h:390
std::size_t size_type
Definition: Buffer.h:124
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Buffer(Buffer &&other) noexcept
Move constructor.
Definition: Buffer.h:223
bool mBufferCreated
Was the buffer created (is it owned) by us.
Definition: Buffer.h:554
Buffer & operator=(const Buffer &other)
Assignment.
Definition: Buffer.h:208
Buffer(T *carray, size_type size)
Use already allocated memory in carray with size size.
Definition: Buffer.h:157
Alloc mAllocator
The allocator used to allocate new memory.
Definition: Buffer.h:556
const T * const_iterator
Definition: Buffer.h:123
size_type mReserved
The real size of the buffer.
Definition: Buffer.h:553
ptrdiff_t difference_type
Definition: Buffer.h:125
T value_type
Definition: Buffer.h:90
Alloc::reference reference
Definition: Buffer.h:120
Provides type trait that indicates whether a type should be serialized "transparently".
allocator_type get_allocator() const
Returns the allocator.
Definition: Buffer.h:314
const_reference front() const
Returns a reference to the first element in the vector container.
Definition: Buffer.h:490
void reserve(size_type reserve)
Allocates new memory if reserved size < new reserved size.
Definition: Buffer.h:323
T * mBuffer
Pointer to the data buffer.
Definition: Buffer.h:551
size_type mSize
The used elements of the buffer.
Definition: Buffer.h:552
size_type sizeInBytes() const
Returns the used size in bytes.
Definition: Buffer.h:298
Buffer(const Buffer &other)
Copy constructor.
Definition: Buffer.h:202
void push_back(const T &x)
Adds a new element at the end of the vector, after its current last element.
Definition: Buffer.h:362
Buffer & operator=(Buffer &&other) noexcept
Move assignment.
Definition: Buffer.h:229
Wrapper class for reflecting arrays.
void pop_front(size_type elements)
Removes the first elements in the vector by copying all remaining data to the front invalidating all ...
Definition: Buffer.h:420
Alloc::pointer pointer
Definition: Buffer.h:118
void swap(Buffer &other)
Swaps the content of this buffer with the other buffer.
Definition: Buffer.h:235
Contains the base interface of all Reflectors, Serializers, etc.
const_pointer data() const
Returns a const pointer to the underlying data.
Definition: Buffer.h:519
T * iterator
Definition: Buffer.h:122
#define MIRA_REFLECT_CALL(ReflectorType, reflector, context, COMMAND)
Whenever a reflection function calls another function that is independently maintained, the call should be marked to the reflector.
Definition: ReflectorMacros.h:109
reference front()
Returns a reference to the first element in the vector container.
Definition: Buffer.h:482
size_type size() const
Returns the used size of the buffer set by resize()
Definition: Buffer.h:293
const_reference at(size_type n) const
The difference between this member function and member operator function operator[] is that vector::a...
Definition: Buffer.h:474
void push_back(const Buffer< T > &data)
Adds new elements to the end of the vector, after its current last element.
Definition: Buffer.h:379
bool empty() const
Checks if the buffer is empty (used size == 0).
Definition: Buffer.h:303
pointer data()
Returns a pointer to the underlying data.
Definition: Buffer.h:514
Buffer()
Default constructor constructing an empty buffer.
Definition: Buffer.h:140
reference at(size_type n)
The difference between this member function and member operator function operator[] is that vector::a...
Definition: Buffer.h:464
const_reference back() const
Returns a reference to the last element in the vector container.
Definition: Buffer.h:506
void reflect(Reflector &r, LogRecord &record)
Non-intrusive reflector for LogRecord.
Definition: LoggingCore.h:137
size_type max_size() const
Returns the maximum size of the buffer.
Definition: Buffer.h:288
Buffer(size_type size)
Definition: Buffer.h:147
Generic buffer class that can be used as a replacement for std::vector whenever copying and reallocat...
Definition: Buffer.h:84
~Buffer()
Destructor.
Definition: Buffer.h:195
std::vector< T > * mTakenVector
Used to take over the data from a vector without copying.
Definition: Buffer.h:558
void push_back(T *data, size_type size)
Adds new elements to the end of the vector, after its current last element.
Definition: Buffer.h:371
Can be specialized for a concrete derived RecursiveMemberReflector to reflect the size of collections...
Definition: ReflectCollection.h:69
void pop_back(size_type elements)
Removes the last elements in the vector, effectively reducing the vector size by elements.
Definition: Buffer.h:399
iterator begin()
Returns an iterator referring to the first element in the vector container.
Definition: Buffer.h:264
void reflectRead(Reflector &r, Buffer< T, Allocator > &c)
Specialization of the non-intrusive reflect for Buffer.
Definition: Buffer.h:565
void resize(size_type size)
Resizes the buffer.
Definition: Buffer.h:350
void clear()
All the elements of the vector are dropped.
Definition: Buffer.h:437
void pop_front()
Removes the first element in the vector by copying all remaining data to the front invalidating all i...
Definition: Buffer.h:412
iterator end()
Returns an iterator referring to the past-the-end element in the vector container.
Definition: Buffer.h:276
void copy(const Buffer &other)
Copies a buffer into this.
Definition: Buffer.h:214
Type trait that indicates whether a type is a collection.
Definition: IsCollection.h:63
const_iterator end() const
Returns an iterator referring to the past-the-end element in the vector container.
Definition: Buffer.h:282
Alloc::const_reference const_reference
Definition: Buffer.h:121
Alloc allocator_type
Definition: Buffer.h:126
Buffer(std::vector< T > &&other)
Constructs a buffer that TAKES OVER all data from the specified vector.
Definition: Buffer.h:183
const_iterator begin() const
Returns an iterator referring to the first element in the vector container.
Definition: Buffer.h:270
size_type capacity() const
Returns the reserved size/capacity of the buffer (Its real size) set by reserve() ...
Definition: Buffer.h:309
reference operator[](size_type n)
Returns a reference to the element at position n in the vector container.
Definition: Buffer.h:446