source: XMLIO_V2/external/include/blitz/memblock.h @ 73

Last change on this file since 73 was 73, checked in by ymipsl, 14 years ago
  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1// -*- C++ -*-
2/***************************************************************************
3 * blitz/memblock.h      MemoryBlock<T> and MemoryBlockReference<T>
4 *
5 * $Id: memblock.h,v 1.18 2005/10/11 21:54:57 julianc Exp $
6 *
7 * Copyright (C) 1997-1999 Todd Veldhuizen <tveldhui@oonumerics.org>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * Suggestions:          blitz-dev@oonumerics.org
20 * Bugs:                 blitz-bugs@oonumerics.org
21 *
22 * For more information, please see the Blitz++ Home Page:
23 *    http://oonumerics.org/blitz/
24 *
25 ***************************************************************************/
26
27#ifndef BZ_MEMBLOCK_H
28#define BZ_MEMBLOCK_H
29
30#include <blitz/blitz.h>
31
32#include <stddef.h>     // ptrdiff_t
33
34#ifdef BZ_THREADSAFE
35 #include <pthread.h>
36#endif
37
38BZ_NAMESPACE(blitz)
39
40enum preexistingMemoryPolicy { 
41  duplicateData, 
42  deleteDataWhenDone, 
43  neverDeleteData
44};
45
46// Forward declaration of MemoryBlockReference
47template<typename T_type> class MemoryBlockReference;
48
49// Class MemoryBlock provides a reference-counted block of memory.  This block
50// may be referred to by multiple vector, matrix and array objects.  The memory
51// is automatically deallocated when the last referring object is destructed.
52// MemoryBlock may be subclassed to provide special allocators.
53template<typename P_type>
54class MemoryBlock {
55
56    friend class MemoryBlockReference<P_type>;
57
58public:
59    typedef P_type T_type;
60
61protected:
62    MemoryBlock()
63    {
64        length_ = 0;
65        data_ = 0;
66        dataBlockAddress_ = 0;
67        references_ = 0;
68
69        BZ_MUTEX_INIT(mutex)
70    }
71
72    explicit MemoryBlock(size_t items)
73    {
74        length_ = items;
75        allocate(length_);
76
77#ifdef BZ_DEBUG_LOG_ALLOCATIONS
78    cout << "MemoryBlock: allocated " << setw(8) << length_
79         << " at " << ((void *)dataBlockAddress_) << endl;
80#endif
81
82        BZASSERT(dataBlockAddress_ != 0);
83
84        references_ = 0;
85
86        BZ_MUTEX_INIT(mutex)
87    }
88
89    MemoryBlock(size_t length, T_type* data)
90    {
91        length_ = length;
92        data_ = data;
93        dataBlockAddress_ = data;
94        references_ = 0;
95        BZ_MUTEX_INIT(mutex)
96    }
97
98    virtual ~MemoryBlock()
99    {
100        if (dataBlockAddress_) 
101        {
102
103#ifdef BZ_DEBUG_LOG_ALLOCATIONS
104    cout << "MemoryBlock:     freed " << setw(8) << length_
105         << " at " << ((void *)dataBlockAddress_) << endl;
106#endif
107
108            deallocate();
109        }
110
111        BZ_MUTEX_DESTROY(mutex)
112    }
113
114    void          addReference()
115    { 
116        BZ_MUTEX_LOCK(mutex)
117        ++references_; 
118
119#ifdef BZ_DEBUG_LOG_REFERENCES
120    cout << "MemoryBlock:    reffed " << setw(8) << length_
121         << " at " << ((void *)dataBlockAddress_) << " (r=" 
122         << (int)references_ << ")" << endl;
123#endif
124        BZ_MUTEX_UNLOCK(mutex)
125
126    }
127
128    T_type* restrict      data() 
129    { 
130        return data_; 
131    }
132
133    const T_type* restrict data()      const
134    { 
135        return data_; 
136    }
137
138    T_type*&      dataBlockAddress() 
139    { 
140        return dataBlockAddress_; 
141    }
142
143    size_t        length()    const
144    { 
145        return length_; 
146    }
147
148    int           removeReference()
149    {
150
151        BZ_MUTEX_LOCK(mutex)
152        int refcount = --references_;
153
154#ifdef BZ_DEBUG_LOG_REFERENCES
155    cout << "MemoryBlock: dereffed  " << setw(8) << length_
156         << " at " << ((void *)dataBlockAddress_) << " (r=" << (int)references_
157         << ")" << endl;
158#endif
159        BZ_MUTEX_UNLOCK(mutex)
160        return refcount;
161    }
162
163    int references() const
164    {
165        BZ_MUTEX_LOCK(mutex)
166        int refcount = references_;
167        BZ_MUTEX_UNLOCK(mutex)
168
169        return refcount;
170    }
171
172protected:
173    inline void allocate(size_t length);
174    void deallocate();
175
176private:   // Disabled member functions
177    MemoryBlock(const MemoryBlock<T_type>&)
178    { }
179
180    void operator=(const MemoryBlock<T_type>&)
181    { }
182
183private:   // Data members
184    T_type * restrict     data_;
185    T_type *              dataBlockAddress_;
186
187#ifdef BZ_DEBUG_REFERENCE_ROLLOVER
188    volatile unsigned char references_;
189#else
190    volatile int references_;
191#endif
192
193    BZ_MUTEX_DECLARE(mutex)
194    size_t  length_;
195};
196
197template<typename P_type>
198class UnownedMemoryBlock : public MemoryBlock<P_type> {
199public:
200    UnownedMemoryBlock(size_t length, P_type* data)
201        : MemoryBlock<P_type>(length,data)
202    {
203        // This ensures that MemoryBlock destructor will not
204        // attempt to delete data
205        MemoryBlock<P_type>::dataBlockAddress() = 0;
206    }
207
208    virtual ~UnownedMemoryBlock()
209    {
210    }
211};
212
213template<typename P_type>
214class NullMemoryBlock : public MemoryBlock<P_type> {
215public:
216    NullMemoryBlock()
217    { 
218        // This ensures that the delete operator will not be invoked
219        // on an instance of NullMemoryBlock in removeReference().
220        MemoryBlock<P_type>::addReference();       
221    }
222
223    virtual ~NullMemoryBlock() 
224    { }
225};
226
227template<typename P_type>
228class MemoryBlockReference {
229
230public:
231    typedef P_type T_type;
232
233protected:
234    T_type * restrict data_;
235
236private:
237    MemoryBlock<T_type>* block_;
238    static NullMemoryBlock<T_type> nullBlock_;
239
240public:
241
242    MemoryBlockReference()
243    {
244        block_ = &nullBlock_;
245        block_->addReference();
246        data_ = 0;
247    }
248
249    MemoryBlockReference(MemoryBlockReference<T_type>& ref, size_t offset=0)
250    {
251        block_ = ref.block_;
252        block_->addReference();
253        data_ = ref.data_ + offset;
254    }
255
256    MemoryBlockReference(size_t length, T_type* data, 
257        preexistingMemoryPolicy deletionPolicy)
258    {
259        // Create a memory block using already allocated memory.
260
261        // Note: if the deletionPolicy is duplicateData, this must
262        // be handled by the leaf class.  In MemoryBlockReference,
263        // this is treated as neverDeleteData; the leaf class (e.g. Array)
264        // must duplicate the data.
265
266        if ((deletionPolicy == neverDeleteData) 
267          || (deletionPolicy == duplicateData))
268            block_ = new UnownedMemoryBlock<T_type>(length, data);
269        else if (deletionPolicy == deleteDataWhenDone)
270            block_ = new MemoryBlock<T_type>(length, data);
271        block_->addReference();
272
273#ifdef BZ_DEBUG_LOG_ALLOCATIONS
274    cout << "MemoryBlockReference: created MemoryBlock at "
275         << ((void*)block_) << endl;
276#endif
277
278        data_ = data;
279    }
280
281    explicit MemoryBlockReference(size_t items)
282    {
283        block_ = new MemoryBlock<T_type>(items);
284        block_->addReference();
285        data_ = block_->data();
286
287#ifdef BZ_DEBUG_LOG_ALLOCATIONS
288    cout << "MemoryBlockReference: created MemoryBlock at "
289         << ((void*)block_) << endl;
290#endif
291
292    }
293
294    void blockRemoveReference()
295    {
296        int refcount = block_->removeReference();
297        if ((refcount == 0) && (block_ != &nullBlock_))
298        {
299#ifdef BZ_DEBUG_LOG_ALLOCATIONS
300    cout << "MemoryBlock: no more refs, delete MemoryBlock object at "
301         << ((void*)block_) << endl;
302#endif
303
304            delete block_;
305        }
306    }
307
308   ~MemoryBlockReference()
309    {
310        blockRemoveReference();
311    }
312
313    int numReferences() const
314    {
315        return block_->references();
316    }
317
318
319protected:
320
321    void changeToNullBlock()
322    {
323        blockRemoveReference();
324        block_ = &nullBlock_;
325        block_->addReference();
326        data_ = 0;
327    }
328
329    void changeBlock(MemoryBlockReference<T_type>& ref, size_t offset=0)
330    {
331        blockRemoveReference();
332        block_ = ref.block_;
333        block_->addReference();
334        data_ = ref.data_ + offset;
335    }
336
337    void newBlock(size_t items)
338    {
339        blockRemoveReference();
340        block_ = new MemoryBlock<T_type>(items);
341        block_->addReference();
342        data_ = block_->data();
343
344#ifdef BZ_DEBUG_LOG_ALLOCATIONS
345    cout << "MemoryBlockReference: created MemoryBlock at "
346         << ((void*)block_) << endl;
347#endif
348    }
349
350private:
351    void operator=(const MemoryBlockReference<T_type>&)
352    { }
353};
354
355
356BZ_NAMESPACE_END
357
358#include <blitz/memblock.cc>
359
360#endif // BZ_MEMBLOCK_H
Note: See TracBrowser for help on using the repository browser.