An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 10700 was 10700, checked in by Michael Tänzer, 7 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.