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

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

Merge the ASIO branch back into trunk

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