added: start working on MemBuffer (an efficient memory buffer)

git-svn-id: svn://ttmath.org/publicrep/pikotools/trunk@421 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2012-07-01 00:39:41 +00:00
parent be8e0d005c
commit 62f0624539
1 changed files with 208 additions and 0 deletions

208
membuffer/membuffer.h Normal file
View File

@ -0,0 +1,208 @@
#ifndef headerfile_picotools_membuffer_membuffer
#define headerfile_picotools_membuffer_membuffer
#include <vector>
namespace PT
{
template<class ItemType, size_t stack_size>
class MemBuffer
{
public:
class Iterator
{
size_t vector_index;
size_t array_index;
bool operator==(const Iterator & i);
bool operator!=(const Iterator & i);
bool operator<(const Iterator & i);
Iterator & operator++(); // prefix ++
Iterator operator++(int); // postfix ++
ItemType & operator*();
};
class ConstIterator
{
};
MemBuffer();
void Append(ItemType item);
void Append(ItemType * item_array, size_t len);
void Size() const;
void Empty() const;
void Reserve();
void Capacity();
void SetMinCapacity();
void Clear(); // frees memory but only to SetMinCapacity()
Iterator Begin();
ConstIterator Begin() const;
Iterator End();
ConstIterator End() const;
// may it's a better to have a static size of dynamic_array items
// so we can have following operators working in O(1)
//ItemType & operator[](size_t i);
//const ItemType operator[](size_t i) const;
private:
struct MemArray
{
size_t size;
size_t size_used;
ItemType * buf;
};
ItemType stack_array[stack_size];
std::vector<MemArray> dynamic_array;
size_t size_used; // the size of all items
size_t reserve_size; // how many memory is reserved
size_t last_allocated_list; // size of the last allocated vector
};
template<class ItemType, size_t stack_size>
MemBuffer<ItemType>::Iterator & MemBuffer<ItemType>::Iterator::operator++()
{
if( vector_index == size_t(-1) )
{
array_index += 1;
if( array_index >= stack_size )
{
array_index = 0;
vector_index = 0;
}
}
else
{
// if not it means that this iterator is pointing at End()
if( vector_index < dynamic_array.size() && array_index < dynamic_array.back().size_used )
{
array_index += 1;
if( array_index >= dynamic_array.back().size )
{
array_index = 0;
vector_index += 1;
}
}
}
return *this;
}
template<class ItemType, size_t stack_size>
MemBuffer<ItemType>::Iterator MemBuffer<ItemType>::Iterator::operator++(int)
{
Iterator old(*this);
operator++();
return old;
}
template<class ItemType, size_t stack_size>
void MemBuffer<ItemType>::MemBuffer()
{
size_used = 0;
list_size = 0;
reserve_size = stack_size;
last_allocated_list = 512; // minimum 1
}
template<class ItemType, size_t stack_size>
void MemBuffer<ItemType>::Append(ItemType item)
{
if( size_used < stack_size )
{
stack_array[size_used];
}
else
{
if( dynamic_array.empty() || dynamic_array.back().size_used >= dynamic_array.back().size )
{
last_allocated_list = last_allocated_list * 2;
dynamic_array.push_back(MemArray());
dynamic_array.back().size = last_allocated_list;
dynamic_array.back().size_used = 0;
dynamic_array.back().buf = new ItemType[last_allocated_list];
reserve_size += last_allocated_list;
}
dynamic_array.back().buf[dynamic_array.back().size_used] = item;
dynamic_array.back().size_used += 1;
}
size_used += 1;
}
template<class ItemType, size_t stack_size>
void MemBuffer<ItemType>::Append(ItemType * item_array, size_t len)
{
// in the future we can add a test
// if the array can be placed directly in the last item from std::list
// the we put it all
if( size_used < stack_size && size_used + len <= stack_size )
{
// may memcpy in the future? need some tests
for(size_t i=0 ; i<len ; ++i)
stack_array[size_used++] = item_array[i];
return;
}
if( !dynamic_array.empty() && dynamic_array.back().size_used + len <= dynamic_array.back().size )
{
ItemType * buf = dynamic_array.back().buf;
size_t bufsize = dynamic_array.back().size_used;
for(size_t i=0 ; i<len ; ++i)
buf[bufsize++] = item_array[i];
dynamic_array.back().size_used += len;
size_used += len;
return;
}
for(size_t i=0 ; i<len ; ++i)
Append(item_array[i]);
}
} // namespace
#endif