Thrill  0.1
buffer.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * thrill/net/buffer.hpp
3  *
4  * Contains binary byte buffer used by most network classes.
5  *
6  * Part of Project Thrill - http://project-thrill.org
7  *
8  * Copyright (C) 2015 Timo Bingmann <[email protected]>
9  *
10  * All rights reserved. Published under the BSD-2 license in the LICENSE file.
11  ******************************************************************************/
12 
13 #pragma once
14 #ifndef THRILL_NET_BUFFER_HEADER
15 #define THRILL_NET_BUFFER_HEADER
16 
17 #include <thrill/common/logger.hpp>
18 
19 #include <algorithm>
20 #include <cassert>
21 #include <cstdlib>
22 #include <string>
23 
24 namespace thrill {
25 namespace net {
26 
27 //! \addtogroup net_layer
28 //! \{
29 
30 /*!
31  * Simple buffer of characters without initialization or growing functionality.
32  *
33  * We use Buffer instead of std::string for handling untyped byte arrays. The
34  * advantage of Buffer is that we have guaranteed direct byte access, and that
35  * it does not initialize memory (faster). A Buffer object is also non-copyable,
36  * which makes sure that we use zero-copy overhead as much as possible.
37  *
38  * This Buffer allows memory using malloc()/realloc()/free().
39  */
40 class Buffer
41 {
42 public:
43  //! value type stored in the buffer
44  using value_type = unsigned char;
45  //! size and offset type of buffer
46  using size_type = size_t;
47 
48  //! simple pointer iterators
49  using iterator = value_type *;
50  //! simple pointer iterators
51  using const_iterator = const value_type *;
52  //! simple pointer references
54  //! simple pointer references
55  using const_reference = const value_type&;
56 
57 private:
58  //! protected constructor used to acquire ownership of a buffer
59  Buffer(bool /* acquire_tag */, void* data, size_type size)
60  : data_(reinterpret_cast<value_type*>(data)), size_(size)
61  { }
62 
63 public:
64  //! \name Construction, Moving, Destruction
65  //! \{
66 
67  //! allocate empty buffer
68  Buffer() noexcept
69  : data_(nullptr), size_(0)
70  { }
71 
72  //! allocate buffer containing n bytes
73  explicit Buffer(size_type n) noexcept
74  : Buffer(true, malloc(n), n)
75  { }
76 
77  //! allocate buffer and COPY data into it.
78  explicit Buffer(const void* data, size_type size)
79  : Buffer(true, malloc(size), size) {
80  const value_type* cdata = reinterpret_cast<const value_type*>(data);
81  std::copy(cdata, cdata + size, data_);
82  }
83 
84  //! non-copyable: delete copy-constructor
85  Buffer(const Buffer&) = delete;
86  //! non-copyable: delete assignment operator
87  Buffer& operator = (const Buffer&) = delete;
88 
89  //! move-construct other buffer into this one
90  Buffer(Buffer&& other) noexcept
91  : data_(other.data_), size_(other.size_) {
92  other.data_ = nullptr;
93  other.size_ = 0;
94  }
95 
96  //! move-assignment of other buffer into this one
97  Buffer& operator = (Buffer&& other) noexcept {
98  if (this != &other) {
99  if (data_) free(data_);
100  data_ = other.data_;
101  size_ = other.size_;
102  other.data_ = nullptr;
103  other.size_ = 0;
104  }
105  return *this;
106  }
107 
108  //! construct Buffer by acquiring ownership of a memory buffer. The memory
109  //! buffer will be FREE()ed (not delete[]-ed).
111  { return Buffer(true, data, size); }
112 
113  //! delete buffer
115  if (data_) free(data_);
116  }
117 
118  //! swap buffer with another one
119  friend void swap(Buffer& a, Buffer& b) noexcept {
120  using std::swap;
121  swap(a.data_, b.data_);
122  swap(a.size_, b.size_);
123  }
124 
125  //! Check for Buffer contents is valid.
126  bool IsValid() const noexcept { return (data_ != nullptr); }
127 
128  //! \}
129 
130  //! \name Data Access
131  //! \{
132 
133  //! return iterator to beginning of Buffer
134  iterator data() noexcept
135  { return data_; }
136  //! return iterator to beginning of Buffer
137  const_iterator data() const noexcept
138  { return data_; }
139 
140  //! return number of items in Buffer
141  size_type size() const noexcept
142  { return size_; }
143 
144  //! return the i-th position of the Buffer
146  assert(i < size_);
147  return *(begin() + i);
148  }
149  //! return constant reference to the i-th position of the Buffer
151  assert(i < size_);
152  return *(begin() + i);
153  }
154 
155  //! \}
156 
157  //! \name Iterator Access
158 
159  //! return mutable iterator to first element
160  iterator begin() noexcept
161  { return data_; }
162  //! return constant iterator to first element
163  const_iterator begin() const noexcept
164  { return data_; }
165  //! return constant iterator to first element
166  const_iterator cbegin() const noexcept
167  { return begin(); }
168 
169  //! return mutable iterator beyond last element
170  iterator end() noexcept
171  { return data_ + size_; }
172  //! return constant iterator beyond last element
173  const_iterator end() const noexcept
174  { return data_ + size_; }
175  //! return constant iterator beyond last element
176  const_iterator cend() const noexcept
177  { return end(); }
178 
179  //! \}
180 
181  //! \name Resize and Filling
182  //! \{
183 
184  //! Zero the whole array content.
185  void Zero() {
186  std::fill(data_, data_ + size_, value_type(0));
187  }
188 
189  //! resize the array to contain exactly new_size items. This should only be
190  //! used if the Buffer was default constructed containing an empty array. It
191  //! should NOT be used to resizing it, since this requires it to copy data.
192  void Resize(size_type new_size) {
193  if (data_)
194  {
195  LOG1 << "Warning: resizing non-empty Buffer";
196  data_ = reinterpret_cast<value_type*>(::realloc(data_, new_size));
197  size_ = new_size;
198  }
199  else
200  {
201  data_ = reinterpret_cast<value_type*>(::malloc(new_size));
202  size_ = new_size;
203  }
204  }
205 
206  //! \}
207 
208  //! \name Output
209  //! \{
210 
211  //! copy contents into std::string
213  if (!data_) return std::string();
214  return std::string(reinterpret_cast<const char*>(data_), size_);
215  }
216 
217  //! copy part of contents into std::string
218  std::string PartialToString(size_t begin, size_t length) const {
219  assert(size_ >= begin + length);
220  return std::string(reinterpret_cast<const char*>(data_ + begin), length);
221  }
222 
223  //! make ostream-able
224  friend std::ostream& operator << (std::ostream& os, const Buffer& b) {
225  return os << "[Buffer size=" << b.size() << "]";
226  }
227 
228  //! \}
229 
230 private:
231  //! the buffer, typed as character data
233 
234  //! size of the buffer.
236 };
237 
238 //! \}
239 
240 } // namespace net
241 } // namespace thrill
242 
243 #endif // !THRILL_NET_BUFFER_HEADER
244 
245 /******************************************************************************/
std::string PartialToString(size_t begin, size_t length) const
copy part of contents into std::string
Definition: buffer.hpp:218
value_type * data_
the buffer, typed as character data
Definition: buffer.hpp:232
void Resize(size_type new_size)
Definition: buffer.hpp:192
#define LOG1
Definition: logger.hpp:28
bool IsValid() const noexcept
Check for Buffer contents is valid.
Definition: buffer.hpp:126
Buffer(Buffer &&other) noexcept
move-construct other buffer into this one
Definition: buffer.hpp:90
const_iterator data() const noexcept
return iterator to beginning of Buffer
Definition: buffer.hpp:137
const_iterator cend() const noexcept
return constant iterator beyond last element
Definition: buffer.hpp:176
Buffer() noexcept
allocate empty buffer
Definition: buffer.hpp:68
friend void swap(Buffer &a, Buffer &b) noexcept
swap buffer with another one
Definition: buffer.hpp:119
const value_type & const_reference
simple pointer references
Definition: buffer.hpp:55
iterator begin() noexcept
return mutable iterator to first element
Definition: buffer.hpp:160
value_type * iterator
simple pointer iterators
Definition: buffer.hpp:49
~Buffer()
delete buffer
Definition: buffer.hpp:114
iterator end() noexcept
return mutable iterator beyond last element
Definition: buffer.hpp:170
iterator data() noexcept
return iterator to beginning of Buffer
Definition: buffer.hpp:134
static Buffer Acquire(void *data, size_type size)
Definition: buffer.hpp:110
unsigned char value_type
value type stored in the buffer
Definition: buffer.hpp:44
void swap(CountingPtr< A, D > &a1, CountingPtr< A, D > &a2) noexcept
Buffer(size_type n) noexcept
allocate buffer containing n bytes
Definition: buffer.hpp:73
void * malloc(size_t size) NOEXCEPT
exported malloc symbol that overrides loading from libc
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
reference operator[](size_type i)
return the i-th position of the Buffer
Definition: buffer.hpp:145
value_type & reference
simple pointer references
Definition: buffer.hpp:53
size_type size_
size of the buffer.
Definition: buffer.hpp:235
Buffer(bool, void *data, size_type size)
protected constructor used to acquire ownership of a buffer
Definition: buffer.hpp:59
void Zero()
Zero the whole array content.
Definition: buffer.hpp:185
std::string ToString() const
copy contents into std::string
Definition: buffer.hpp:212
Simple buffer of characters without initialization or growing functionality.
Definition: buffer.hpp:40
Buffer & operator=(const Buffer &)=delete
non-copyable: delete assignment operator
friend std::ostream & operator<<(std::ostream &os, const Buffer &b)
make ostream-able
Definition: buffer.hpp:224
const_iterator end() const noexcept
return constant iterator beyond last element
Definition: buffer.hpp:173
const_iterator cbegin() const noexcept
return constant iterator to first element
Definition: buffer.hpp:166
const value_type * const_iterator
simple pointer iterators
Definition: buffer.hpp:51
void free(void *ptr) NOEXCEPT
exported free symbol that overrides loading from libc
size_t size_type
size and offset type of buffer
Definition: buffer.hpp:46
const_iterator begin() const noexcept
return constant iterator to first element
Definition: buffer.hpp:163
void * realloc(void *ptr, size_t size) NOEXCEPT
exported realloc() symbol that overrides loading from libc
Buffer(const void *data, size_type size)
allocate buffer and COPY data into it.
Definition: buffer.hpp:78
size_type size() const noexcept
return number of items in Buffer
Definition: buffer.hpp:141