source: Sophya/trunk/SophyaExt/Blitz/blitz/memblock.h@ 3111

Last change on this file since 3111 was 221, checked in by ansari, 26 years ago

Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99

File size: 7.7 KB
Line 
1/***************************************************************************
2 * blitz/memblock.h MemoryBlock<T> and MemoryBlockReference<T>
3 *
4 * $Id: memblock.h,v 1.1.1.1 1999-04-09 17:58:59 ansari Exp $
5 *
6 * Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * Suggestions: blitz-suggest@cybervision.com
19 * Bugs: blitz-bugs@cybervision.com
20 *
21 * For more information, please see the Blitz++ Home Page:
22 * http://seurat.uwaterloo.ca/blitz/
23 *
24 ***************************************************************************
25 * $Log: not supported by cvs2svn $
26 * Revision 1.7 1998/06/15 16:07:01 tveldhui
27 * When a memory block is created from an existing block of data,
28 * add an additional reference count so that makeUnique() will
29 * create a copy of the data.
30 *
31 * Revision 1.6 1998/03/14 00:04:47 tveldhui
32 * 0.2-alpha-05
33 *
34 * Revision 1.5 1997/07/16 14:51:20 tveldhui
35 * Update: Alpha release 0.2 (Arrays)
36 *
37 * Revision 1.4 1997/01/24 14:42:00 tveldhui
38 * Periodic RCS update
39 *
40 * Revision 1.3 1997/01/23 03:28:28 tveldhui
41 * Periodic RCS update
42 *
43 * Revision 1.2 1997/01/13 22:19:58 tveldhui
44 * Periodic RCS update
45 *
46 * Revision 1.1 1996/11/11 17:29:13 tveldhui
47 * Initial revision
48 *
49 *
50 ***************************************************************************
51 *
52 */
53
54#ifndef __BZ_MEMBLOCK_H__
55#define __BZ_MEMBLOCK_H__
56
57#ifndef BZ_BLITZ_H
58 #include <blitz/blitz.h>
59#endif
60
61#include <stddef.h> // ptrdiff_t
62
63BZ_NAMESPACE(blitz)
64
65// Forward declaration of MemoryBlockReference
66template<class T_type> class MemoryBlockReference;
67
68// Class MemoryBlock provides a reference-counted block of memory. This block
69// may be referred to by multiple vector, matrix and array objects. The memory
70// is automatically deallocated when the last referring object is destructed.
71// MemoryBlock may be subclassed to provide special allocators.
72template<class P_type>
73class MemoryBlock {
74
75 friend class MemoryBlockReference<P_type>;
76
77public:
78 typedef P_type T_type;
79
80protected:
81 MemoryBlock()
82 {
83 length_ = 0;
84 data_ = 0;
85 dataBlockAddress_ = 0;
86 references_ = 0;
87 ownData_ = 0;
88 }
89
90 _bz_explicit MemoryBlock(size_t items)
91 {
92 length_ = items;
93 allocate(length_);
94
95#ifdef BZ_DEBUG_LOG_ALLOCATIONS
96 cout << "MemoryBlock: allocated " << setw(8) << length_
97 << " at " << ((void *)dataBlockAddress_) << endl;
98#endif
99
100 BZASSERT(dataBlockAddress_ != 0);
101
102 references_ = 0;
103 ownData_ = 1;
104 }
105
106 MemoryBlock(size_t length, T_type* _bz_restrict data)
107 {
108 length_ = length;
109 data_ = data;
110 dataBlockAddress_ = 0;
111 references_ = 0;
112 ownData_ = 0;
113 }
114
115 virtual ~MemoryBlock()
116 {
117 if ((dataBlockAddress_) && (ownData_))
118 {
119
120#ifdef BZ_DEBUG_LOG_ALLOCATIONS
121 cout << "MemoryBlock: freed " << setw(8) << length_
122 << " at " << ((void *)dataBlockAddress_) << endl;
123#endif
124
125 delete [] dataBlockAddress_;
126 }
127 }
128
129 void addReference()
130 {
131 ++references_;
132
133#ifdef BZ_DEBUG_LOG_REFERENCES
134 cout << "MemoryBlock: reffed " << setw(8) << length_
135 << " at " << ((void *)dataBlockAddress_) << " (r="
136 << references_ << ")" << endl;
137#endif
138
139 }
140
141 T_type* _bz_restrict data()
142 {
143 return data_;
144 }
145
146 const T_type* _bz_restrict data() const
147 {
148 return data_;
149 }
150
151 size_t length() const
152 {
153 return length_;
154 }
155
156 void removeReference()
157 {
158 --references_;
159
160#ifdef BZ_DEBUG_LOG_REFERENCES
161 cout << "MemoryBlock: dereffed " << setw(8) << length_
162 << " at " << ((void *)dataBlockAddress_) << " (r=" << references_
163 << ")" << endl;
164#endif
165
166 if (!references_)
167 delete this;
168 }
169
170 int references() const
171 {
172 return references_;
173 }
174
175protected:
176 inline void allocate(int length);
177
178private: // Disabled member functions
179 MemoryBlock(const MemoryBlock<T_type>&)
180 { }
181
182 void operator=(const MemoryBlock<T_type>&)
183 { }
184
185private: // Data members
186 T_type * _bz_restrict data_;
187 T_type * _bz_restrict dataBlockAddress_;
188 int references_;
189 size_t length_;
190 int ownData_;
191};
192
193template<class P_type>
194class NullMemoryBlock : public MemoryBlock<P_type> {
195public:
196 NullMemoryBlock()
197 {
198 // This ensures that the delete operator will not be invoked
199 // on an instance of NullMemoryBlock in removeReference().
200 this->addReference();
201 }
202
203 virtual ~NullMemoryBlock()
204 { }
205};
206
207template<class P_type>
208class MemoryBlockReference {
209
210public:
211 typedef P_type T_type;
212
213 MemoryBlockReference()
214 {
215 block_ = &nullBlock_;
216 block_->addReference();
217
218#ifndef BZ_TEMPLATE_STATIC_INIT
219 // This compiler doesn't handle static initialization
220 // and templates properly. Give the NullMemoryBlock
221 // another reference to make sure it doesn't delete
222 // itself and cause a seg fault when we dereference it.
223 block_->addReference();
224#endif
225
226 data_ = 0;
227 }
228
229 MemoryBlockReference(MemoryBlockReference<T_type>& ref)
230 {
231 block_ = ref.block_;
232 block_->addReference();
233 data_ = block_->data();
234 }
235
236 MemoryBlockReference(MemoryBlockReference<T_type>& ref, size_t offset)
237 {
238 block_ = ref.block_;
239 block_->addReference();
240 data_ = block_->data() + offset;
241 }
242
243 MemoryBlockReference(size_t length, T_type* data)
244 {
245 // Create a memory block using already allocated memory. Note
246 // that the memory will not be freed when no longer being
247 // referenced.
248 block_ = new MemoryBlock<T_type>(length, data);
249 block_->addReference();
250
251 // This extra reference indicates that another object somewhere
252 // has a pointer to the data. This is necessary so that makeUnique()
253 // will create a copy of the data. -- TV 19980615
254 block_->addReference();
255 data_ = data;
256 }
257
258 _bz_explicit MemoryBlockReference(size_t items)
259 {
260 block_ = new MemoryBlock<T_type>(items);
261 block_->addReference();
262 data_ = block_->data();
263 }
264
265 ~MemoryBlockReference()
266 {
267 block_->removeReference();
268 }
269
270 int numReferences() const
271 {
272 return block_->references();
273 }
274
275protected:
276
277 void changeToNullBlock()
278 {
279 block_->removeReference();
280 block_ = &nullBlock_;
281 block_->addReference();
282 data_ = 0;
283 }
284
285 void changeBlock(MemoryBlockReference<T_type>& ref, size_t offset)
286 {
287 block_->removeReference();
288 block_ = ref.block_;
289 block_->addReference();
290 data_ = block_->data() + offset;
291 }
292
293 void newBlock(size_t items)
294 {
295 block_->removeReference();
296 block_ = new MemoryBlock<T_type>(items);
297 block_->addReference();
298 data_ = block_->data();
299 }
300
301private:
302 void operator=(const MemoryBlockReference<T_type>&)
303 { }
304
305private:
306 MemoryBlock<T_type>* block_;
307 static NullMemoryBlock<T_type> nullBlock_;
308
309protected:
310 T_type * _bz_restrict data_;
311};
312
313
314BZ_NAMESPACE_END
315
316#include <blitz/memblock.cc>
317
318#endif // __BZ_MEMBLOCK_H__
Note: See TracBrowser for help on using the repository browser.