📄 memblock.h
字号:
/***************************************************************************
* blitz/memblock.h MemoryBlock<T> and MemoryBlockReference<T>
*
* $Id: memblock.h,v 1.8 1998/12/06 00:00:35 tveldhui Exp $
*
* Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Suggestions: blitz-suggest@cybervision.com
* Bugs: blitz-bugs@cybervision.com
*
* For more information, please see the Blitz++ Home Page:
* http://seurat.uwaterloo.ca/blitz/
*
***************************************************************************
* $Log: memblock.h,v $
* Revision 1.8 1998/12/06 00:00:35 tveldhui
* Prior to adding UnownedMemoryBlock
*
* Revision 1.7 1998/06/15 16:07:01 tveldhui
* When a memory block is created from an existing block of data,
* add an additional reference count so that makeUnique() will
* create a copy of the data.
*
* Revision 1.6 1998/03/14 00:04:47 tveldhui
* 0.2-alpha-05
*
* Revision 1.5 1997/07/16 14:51:20 tveldhui
* Update: Alpha release 0.2 (Arrays)
*
* Revision 1.4 1997/01/24 14:42:00 tveldhui
* Periodic RCS update
*
* Revision 1.3 1997/01/23 03:28:28 tveldhui
* Periodic RCS update
*
* Revision 1.2 1997/01/13 22:19:58 tveldhui
* Periodic RCS update
*
* Revision 1.1 1996/11/11 17:29:13 tveldhui
* Initial revision
*
*
***************************************************************************
*
*/
#ifndef __BZ_MEMBLOCK_H__
#define __BZ_MEMBLOCK_H__
#ifndef BZ_BLITZ_H
#include <blitz/blitz.h>
#endif
#ifndef BZ_NUMTRAIT_H
#include <blitz/numtrait.h>
#endif
#include <stddef.h> // ptrdiff_t
BZ_NAMESPACE(blitz)
enum preexistingMemoryPolicy {
duplicateData,
deleteDataWhenDone,
neverDeleteData
};
// Forward declaration of MemoryBlockReference
template<class T_type> class MemoryBlockReference;
// Class MemoryBlock provides a reference-counted block of memory. This block
// may be referred to by multiple vector, matrix and array objects. The memory
// is automatically deallocated when the last referring object is destructed.
// MemoryBlock may be subclassed to provide special allocators.
template<class P_type>
class MemoryBlock {
friend class MemoryBlockReference<P_type>;
public:
typedef P_type T_type;
protected:
MemoryBlock()
{
length_ = 0;
data_ = 0;
dataBlockAddress_ = 0;
references_ = 0;
}
_bz_explicit MemoryBlock(size_t items)
{
length_ = items;
allocate(length_);
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlock: allocated " << setw(8) << length_
<< " at " << ((void *)dataBlockAddress_) << endl;
#endif
BZASSERT(dataBlockAddress_ != 0);
references_ = 0;
}
MemoryBlock(size_t length, T_type* _bz_restrict data)
{
length_ = length;
data_ = data;
dataBlockAddress_ = 0;
references_ = 0;
}
virtual ~MemoryBlock()
{
if (dataBlockAddress_)
{
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlock: freed " << setw(8) << length_
<< " at " << ((void *)dataBlockAddress_) << endl;
#endif
deallocate();
}
}
void addReference()
{
++references_;
#ifdef BZ_DEBUG_LOG_REFERENCES
cout << "MemoryBlock: reffed " << setw(8) << length_
<< " at " << ((void *)dataBlockAddress_) << " (r="
<< references_ << ")" << endl;
#endif
}
T_type* _bz_restrict data()
{
return data_;
}
const T_type* _bz_restrict data() const
{
return data_;
}
size_t length() const
{
return length_;
}
void removeReference()
{
--references_;
#ifdef BZ_DEBUG_LOG_REFERENCES
cout << "MemoryBlock: dereffed " << setw(8) << length_
<< " at " << ((void *)dataBlockAddress_) << " (r=" << references_
<< ")" << endl;
#endif
if (!references_)
{
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlock: no more refs, delete MemoryBlock object at "
<< ((void*)this) << endl;
#endif
delete this;
}
}
int references() const
{
return references_;
}
protected:
inline void allocate(int length);
void deallocate();
private: // Disabled member functions
MemoryBlock(const MemoryBlock<T_type>&)
{ }
void operator=(const MemoryBlock<T_type>&)
{ }
private: // Data members
T_type * _bz_restrict data_;
T_type * _bz_restrict dataBlockAddress_;
int references_;
size_t length_;
};
template<class P_type>
class UnownedMemoryBlock : public MemoryBlock<P_type> {
public:
UnownedMemoryBlock(size_t length, P_type* _bz_restrict data)
: MemoryBlock<P_type>(length,data)
{
}
virtual ~UnownedMemoryBlock()
{
}
};
template<class P_type>
class NullMemoryBlock : public MemoryBlock<P_type> {
public:
NullMemoryBlock()
{
// This ensures that the delete operator will not be invoked
// on an instance of NullMemoryBlock in removeReference().
this->addReference();
}
virtual ~NullMemoryBlock()
{ }
};
template<class P_type>
class MemoryBlockReference {
public:
typedef P_type T_type;
MemoryBlockReference()
{
block_ = &nullBlock_;
block_->addReference();
// The C++ standard makes no guarantees about static
// initialization and templates. Thus this kludge:
// give the NullMemoryBlock another reference to make
// sure it doesn't delete itself and cause a seg fault
// when we dereference it.
block_->addReference();
data_ = 0;
}
MemoryBlockReference(MemoryBlockReference<T_type>& ref)
{
block_ = ref.block_;
block_->addReference();
data_ = block_->data();
}
MemoryBlockReference(MemoryBlockReference<T_type>& ref, size_t offset)
{
block_ = ref.block_;
block_->addReference();
data_ = block_->data() + offset;
}
MemoryBlockReference(size_t length, T_type* data,
preexistingMemoryPolicy deletionPolicy)
{
// Create a memory block using already allocated memory.
// Note: if the deletionPolicy is duplicateData, this must
// be handled by the leaf class. In MemoryBlockReference,
// this is treated as neverDeleteData; the leaf class (e.g. Array)
// must duplicate the data.
if ((deletionPolicy == neverDeleteData)
|| (deletionPolicy == duplicateData))
block_ = new UnownedMemoryBlock<T_type>(length, data);
else if (deletionPolicy == deleteDataWhenDone)
block_ = new MemoryBlock<T_type>(length, data);
block_->addReference();
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlockReference: created MemoryBlock at "
<< ((void*)block_) << endl;
#endif
data_ = data;
}
_bz_explicit MemoryBlockReference(size_t items)
{
block_ = new MemoryBlock<T_type>(items);
block_->addReference();
data_ = block_->data();
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlockReference: created MemoryBlock at "
<< ((void*)block_) << endl;
#endif
}
~MemoryBlockReference()
{
block_->removeReference();
}
int numReferences() const
{
return block_->references();
}
protected:
void changeToNullBlock()
{
block_->removeReference();
block_ = &nullBlock_;
block_->addReference();
data_ = 0;
}
void changeBlock(MemoryBlockReference<T_type>& ref, size_t offset)
{
block_->removeReference();
block_ = ref.block_;
block_->addReference();
data_ = block_->data() + offset;
}
void newBlock(size_t items)
{
block_->removeReference();
block_ = new MemoryBlock<T_type>(items);
block_->addReference();
data_ = block_->data();
#ifdef BZ_DEBUG_LOG_ALLOCATIONS
cout << "MemoryBlockReference: created MemoryBlock at "
<< ((void*)block_) << endl;
#endif
}
private:
void operator=(const MemoryBlockReference<T_type>&)
{ }
protected:
T_type * _bz_restrict data_;
private:
MemoryBlock<T_type>* block_;
static NullMemoryBlock<T_type> nullBlock_;
};
BZ_NAMESPACE_END
#include <blitz/memblock.cc>
#endif // __BZ_MEMBLOCK_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -