source: source/ariba/utility/transport/messages/shared_buffer.hpp@ 12766

Last change on this file since 12766 was 12060, checked in by hock@…, 11 years ago

Reintegrate branch: 20130111-hock-message_classes

improvements:

  • new message classes (reboost, zero-copy)
  • "fast path" for direct links (skip overlay layer)
  • link-properties accessible from the application
  • SystemQueue can call boost::bind functions
  • protlib compatibility removed (32bit overhead saved in every message)
  • addressing2
  • AddressDiscovery discoveres only addresses on which we're actually listening
  • ariba serialization usage reduced (sill used in OverlayMsg)
  • Node::connect, easier and cleaner interface to start-up ariba from the application
  • ariba configs via JSON, XML, etc (boost::property_tree)
  • keep-alive overhead greatly reduced
  • (relayed) overlay links can actually be closed now
  • lost messages are detected in most cases
  • notification to the application when link is transformed into direct-link
  • overlay routing: send message to second best hop if it would be dropped otherwise
  • SequenceNumbers (only mechanisms, so for: upward compatibility)
  • various small fixes


regressions:

  • bluetooth is not yet working again
  • bootstrap modules deactivated
  • liblog4xx is not working (use cout-logging)

This patch brings great performance and stability improvements at cost of backward compatibility.
Also bluetooth and the bootstrap modules have not been ported to the new interfaces, yet.

File size: 5.7 KB
Line 
1//-----------------------------------------------------------------------------
2// Part of reboost (http://reboost.org). Released under the
3// BSD 2-clause license (http://www.opensource.org/licenses/bsd-license.php).
4// Copyright 2012, Sebastian Mies <mies@reboost.org> --- All rights reserved.
5//-----------------------------------------------------------------------------
6
7#ifndef REBOOST_SHARED_BUFFER_HPP_
8#define REBOOST_SHARED_BUFFER_HPP_
9
10#include <cstring>
11#include <string>
12#include <boost/shared_ptr.hpp>
13
14#include "ariba/config.h"
15#ifdef DEBUG
16#include <boost/thread/mutex.hpp>
17#endif
18
19#include "buffer.hpp"
20
21#include <stdexcept>
22
23namespace reboost {
24
25class illegal_sub_buffer: public std::runtime_error
26{
27public:
28 /** Takes a character string describing the error. */
29 explicit illegal_sub_buffer(const std::string& __arg) :
30 std::runtime_error(__arg)
31 {
32 }
33
34 virtual ~illegal_sub_buffer() throw() {}
35};
36
37/**
38 * A simple shared buffer.
39 *
40 * Important: if not shared, a buffer is writable. After the buffer is shared,
41 * the buffer is immutable. It uses shared_ptr/default allocators and prints
42 * error messages to <tt>cerr</tt> if buffers leaked at the end of the
43 * program.
44 *
45 * @author Sebastian Mies <mies@reboost.org>
46 */
47class shared_buffer_t: public buffer_t {
48 typedef shared_buffer_t self;
49private:
50 static void onexit();
51 static size_t init();
52
53#ifdef DEBUG
54 static size_t allocated_buffers;
55 static boost::mutex allocated_buffers_mutex;
56#endif
57
58 class deleteable_buffer: public buffer_t {
59 public:
60 deleteable_buffer(bsize_t size) :
61 buffer_t(size)
62 {
63
64#ifdef DEBUG
65 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
66 allocated_buffers++;
67#endif
68
69 }
70
71 deleteable_buffer(boctet_t* data, bsize_t size) :
72 buffer_t(size, data)
73 {
74
75#ifdef DEBUG
76 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
77 allocated_buffers++;
78#endif
79
80 }
81
82 ~deleteable_buffer() {
83 if (!is_null()) delete[] data_;
84
85#ifdef DEBUG
86 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
87 allocated_buffers--;
88#endif
89
90 }
91 };
92 boost::shared_ptr<deleteable_buffer> parent;
93
94public:
95 /// create null-buffer
96 inline shared_buffer_t() :
97 buffer_t(), parent() {
98 }
99
100 /// create a shared buffer of a specific size
101 inline shared_buffer_t(bsize_t size) :
102 buffer_t(), parent(new deleteable_buffer(size)) {
103 buffer_t::operator=(*parent);
104 }
105
106 /// create shared buffer from string
107 inline shared_buffer_t(const char* string) :
108 buffer_t(), parent() {
109 parent.reset(new deleteable_buffer(strlen(string)));
110 memcpy(parent->mutable_data(),string,parent->size());
111 data(parent->mutable_data()); size(parent->size());
112 }
113
114 /// create shared buffer from buffer
115 /// ----> ALTERED BEHAVIOUR:
116 /// ----> This constructor transfers ownership rater than copying the data.
117 inline shared_buffer_t(boctet_t* buffer, bsize_t size) :
118 buffer_t(size, buffer),
119 parent(new deleteable_buffer(buffer, size))
120 {
121 }
122
123// /// XXX debug... copy!
124// /// create shared buffer from buffer
125// inline shared_buffer_t(const char* buffer, bsize_t size) :
126// buffer_t(), parent(new deleteable_buffer(size)) {
127// memcpy(parent->mutable_data(), buffer, parent->size());
128// data(parent->mutable_data()); this->size(parent->size());
129// }
130
131 /// clone data from a normal buffer
132 inline shared_buffer_t(const buffer_t& rhs) :
133 buffer_t(), parent(new deleteable_buffer(rhs.size())) {
134 buffer_t::operator=(*parent);
135 rhs.copy_to(*parent, 0);
136 }
137
138 /// copy constructor
139 inline shared_buffer_t(const self& rhs) :
140 buffer_t(rhs), parent(rhs.parent) {
141 }
142
143 /// copy a buffer pointer and size.
144 inline self& operator=(const self& rhs) {
145 parent = rhs.parent;
146 buffer_t::operator=(rhs);
147 return (*this);
148 }
149
150 /// return sub-buffer.
151 inline self operator()(bsize_t index, bsize_t size = 0) const
152 {
153 // special cases
154 if ( index + size > size_ )
155 {
156 // empty sub-buffer
157 if ( index == size_ )
158 {
159 self n;
160 return n;
161 }
162
163 // ERROR: index out of bounds
164 throw illegal_sub_buffer("Index or size out of bounds in shared_buffer");
165 }
166
167 // regular case
168 self n(*this);
169 n.data_ += index;
170 if (size == 0) n.size_ -= index;
171 else n.size_ = size;
172 return (n);
173 }
174
175 /// returns the number of references
176 inline size_t use_count() const {
177 return (parent.use_count());
178 }
179
180 /// returns true, if this is root buffer
181 inline bool is_root() const {
182 return ((parent.get() != NULL) && (this->data() == parent->data()) && (
183 this->size() == parent->size()));
184 }
185
186 /// returns true, if the buffer is not shared
187 inline bool is_unique() const {
188 return parent.unique();
189 }
190
191 /// makes the buffer unique / not shared by copying the contents
192 inline void make_unique() {
193 if (is_unique()) return;
194 boost::shared_ptr<deleteable_buffer> old = parent;
195 parent.reset(new deleteable_buffer(old->size()));
196 buffer_t::data(parent->mutable_data());
197 old->copy_to(*parent,0);
198 }
199
200 /// resize the shared buffer (and make unique)
201 inline void resize( bsize_t new_size ) {
202 boost::shared_ptr<deleteable_buffer> old = parent;
203 parent.reset(new deleteable_buffer(new_size));
204 buffer_t::data(parent->mutable_data());
205 (*old)(0,new_size).copy_to(*parent,0);
206 size_ = new_size;
207 }
208
209 /// returns a pointer to mutable data, if shared_buffer is not shared yet.
210 inline boctet_t * mutable_data() {
211 assert(parent.unique());
212 return buffer_t::mutable_data();
213 }
214
215 /// drop reference to buffer
216 inline void reset() {
217 parent.reset();
218 data(NULL);
219 size(0);
220 }
221
222 /// concatenate buffers
223 self operator+( const buffer_t& rhs ) const {
224 self nb(size()+rhs.size());
225 this->copy_to(nb,0);
226 rhs.copy_to(nb,size());
227 return nb;
228 }
229};
230
231} /* namespace reboost */
232
233#endif /* REBOOST_SHARED_BUFFER_HPP_ */
Note: See TracBrowser for help on using the repository browser.