1.overwrite old element
2.not thread-safe
3.bitwise instead of modulo operation
#ifndef _CIRCULAR_BUFFER_H_2021_03_12
#define _CIRCULAR_BUFFER_H_2021_03_12
#include <vector>
#include <iostream>
inline bool is_power_of_2(unsigned int v)
{
return v && (!(v & (v - 1)));
}
inline unsigned int roundup_pow_of_2(unsigned int v)
{
if (v == 0)
return 0;
unsigned int tmp = 1U;
while (v >>= 1)
{
tmp <<= 1;
}
return tmp <<= 1;
}
template <typename Ty_>
class CircularBuffer
{
public:
explicit CircularBuffer(unsigned int max_size = 128)
{
static_assert(!std::is_pointer<Ty_>::value, "not support pointers");
//static_assert(max_size > 0, "max size must be greater than zero");
if (max_size <= 0 || max_size > (1U << (sizeof(max_size) * CHAR_BIT - 1)))
max_size = 128;
if (!is_power_of_2(max_size))
{
m_capacity = roundup_pow_of_2(max_size);
}
else
{
m_capacity = max_size;
}
m_buffer.resize(m_capacity);
}
void push_back(const Ty_ &e)
{
m_buffer[m_write_index & (m_capacity - 1)] = e;
m_write_index++;
m_size++;
if (m_size > m_capacity || m_size == 0)
{
m_size = m_capacity;
}
}
void pop_front()
{
if (0 >= m_size)
return;
if (m_size == m_capacity)
{
m_read_index = m_write_index;
}
m_read_index++;
m_size--;
return;
}
//return value undefined if index >= m_size
Ty_ peek_at(unsigned int index) const
{
assert(index < m_size);
m_size == m_capacity ? index += m_write_index : index += m_read_index;
index &= (m_capacity - 1);
return m_buffer[index];
}
bool peek_at(unsigned int index, Ty_ & val) const
{
if(index >= m_size) return false;
m_size == m_capacity ? index += m_write_index : index += m_read_index;
index &= (m_capacity - 1);
val = m_buffer[index]
return true;
}
unsigned int size() const
{
return m_size;
}
unsigned int capacity() const
{
return m_capacity;
}
void print() const
{
unsigned int size = this->size();
if (0 == size)
{
std::cout << "empty" << std::endl;
return;
}
unsigned int index = 0;
while (index < size)
{
std::cout << peek_at(index) << " ";
index++;
}
std::cout << std::endl;
}
private:
//Ty_ * m_buffer;
std::vector<Ty_> m_buffer;
unsigned int m_read_index{0};
unsigned int m_write_index{0};
unsigned int m_size{0};
unsigned int m_capacity{0};
};
//test case
void test_circular_buffer()
{
constexpr int max_size = 3;
//not support, fail when compile
//CircularBuffer<int*> cb_pointer;
CircularBuffer<int> cb(max_size);
cb.print();
cb.push_back(1);
cb.push_back(2);
cb.push_back(3);
cb.push_back(4);
cb.print();
cb.push_back(5);
cb.push_back(6);
cb.print();
cb.print();
cb.pop_front();
cb.print();
cb.pop_front();
cb.pop_front();
cb.pop_front();
cb.pop_front();
cb.pop_front();
cb.print();
}
#endif