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

Last change on this file since 10788 was 10700, checked in by Michael Tänzer, 12 years ago

Merge CMake branch into trunk

File size: 4.9 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 <boost/shared_ptr.hpp>
12
13#include "ariba/config.h"
14#ifdef DEBUG
15#include <boost/thread/mutex.hpp>
16#endif
17
18#include "buffer.hpp"
19
20namespace reboost {
21
22/**
23 * A simple shared buffer.
24 *
25 * Important: if not shared, a buffer is writable. After the buffer is shared,
26 * the buffer is immutable. It uses shared_ptr/default allocators and prints
27 * error messages to <tt>cerr</tt> if buffers leaked at the end of the
28 * program.
29 *
30 * @author Sebastian Mies <mies@reboost.org>
31 */
32class shared_buffer_t: public buffer_t {
33 typedef shared_buffer_t self;
34private:
35 static void onexit();
36 static size_t init();
37
38#ifdef DEBUG
39 static size_t allocated_buffers;
40 static boost::mutex allocated_buffers_mutex;
41#endif
42
43 class deleteable_buffer: public buffer_t {
44 public:
45 deleteable_buffer(bsize_t size) :
46 buffer_t(size)
47 {
48
49#ifdef DEBUG
50 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
51 allocated_buffers++;
52#endif
53
54 }
55
56 deleteable_buffer(boctet_t* data, bsize_t size) :
57 buffer_t(size, data)
58 {
59
60#ifdef DEBUG
61 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
62 allocated_buffers++;
63#endif
64
65 }
66
67 ~deleteable_buffer() {
68 if (!is_null()) delete[] data_;
69
70#ifdef DEBUG
71 boost::mutex::scoped_lock lock(allocated_buffers_mutex);
72 allocated_buffers--;
73#endif
74
75 }
76 };
77 boost::shared_ptr<deleteable_buffer> parent;
78
79public:
80 /// create null-buffer
81 inline shared_buffer_t() :
82 buffer_t(), parent() {
83 }
84
85 /// create a shared buffer of a specific size
86 inline shared_buffer_t(bsize_t size) :
87 buffer_t(), parent(new deleteable_buffer(size)) {
88 buffer_t::operator=(*parent);
89 }
90
91 /// create shared buffer from string
92 inline shared_buffer_t(const char* string) :
93 buffer_t(), parent() {
94 parent.reset(new deleteable_buffer(strlen(string)));
95 memcpy(parent->mutable_data(),string,parent->size());
96 data(parent->mutable_data()); size(parent->size());
97 }
98
99 /// create shared buffer from buffer
100 /// ----> ALTERED BEHAVIOUR:
101 /// ----> This constructor transfers ownership rater than copying the data.
102 inline shared_buffer_t(boctet_t* buffer, bsize_t size) :
103 buffer_t(size, buffer),
104 parent(new deleteable_buffer(buffer, size))
105 {
106// memcpy(parent->mutable_data(), buffer, parent->size());
107// data(parent->mutable_data());
108// this->size(parent->size());
109 }
110
111 /// clone data from a normal buffer
112 inline shared_buffer_t(const buffer_t& rhs) :
113 buffer_t(), parent(new deleteable_buffer(rhs.size())) {
114 buffer_t::operator=(*parent);
115 rhs.copy_to(*parent, 0);
116 }
117
118 /// copy constructor
119 inline shared_buffer_t(const self& rhs) :
120 buffer_t(rhs), parent(rhs.parent) {
121 }
122
123 /// copy a buffer pointer and size.
124 inline self& operator=(const self& rhs) {
125 parent = rhs.parent;
126 buffer_t::operator=(rhs);
127 return (*this);
128 }
129
130 /// return sub-buffer.
131 inline self operator()(bsize_t index, bsize_t size = 0) const {
132 self n(*this);
133 n.data_ += index;
134 if (size == 0) n.size_ -= index;
135 else n.size_ = size;
136 return (n);
137 }
138
139 /// returns the number of references
140 inline size_t use_count() const {
141 return (parent.use_count());
142 }
143
144 /// returns true, if this is root buffer
145 inline bool is_root() const {
146 return ((parent.get() != NULL) && (this->data() == parent->data()) && (
147 this->size() == parent->size()));
148 }
149
150 /// returns true, if the buffer is not shared
151 inline bool is_unique() const {
152 return parent.unique();
153 }
154
155 /// makes the buffer unique / not shared by copying the contents
156 inline void make_unique() {
157 if (is_unique()) return;
158 boost::shared_ptr<deleteable_buffer> old = parent;
159 parent.reset(new deleteable_buffer(old->size()));
160 buffer_t::data(parent->mutable_data());
161 old->copy_to(*parent,0);
162 }
163
164 /// resize the shared buffer (and make unique)
165 inline void resize( bsize_t new_size ) {
166 boost::shared_ptr<deleteable_buffer> old = parent;
167 parent.reset(new deleteable_buffer(new_size));
168 buffer_t::data(parent->mutable_data());
169 (*old)(0,new_size).copy_to(*parent,0);
170 size_ = new_size;
171 }
172
173 /// returns a pointer to mutable data, if shared_buffer is not shared yet.
174 inline boctet_t * mutable_data() {
175 assert(parent.unique());
176 return buffer_t::mutable_data();
177 }
178
179 /// drop reference to buffer
180 inline void reset() {
181 parent.reset();
182 data(NULL);
183 size(0);
184 }
185
186 /// concatenate buffers
187 self operator+( const buffer_t& rhs ) const {
188 self nb(size()+rhs.size());
189 this->copy_to(nb,0);
190 rhs.copy_to(nb,size());
191 return nb;
192 }
193};
194
195} /* namespace reboost */
196
197#endif /* REBOOST_SHARED_BUFFER_HPP_ */
Note: See TracBrowser for help on using the repository browser.