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:
parent
be8e0d005c
commit
62f0624539
|
@ -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
|
||||
|
Loading…
Reference in New Issue