I am learning circular / cyclic buffer using this link. Here is the code that I have written so far:
#include <iostream>
#include <memory>
#include <cstddef>
class CircularBuffer
{
std::unique_ptr<int[]> u_ptr;
std::size_t head;
std::size_t tail;
const std::size_t capacity;
bool full_v;
public:
CircularBuffer(std::size_t);
void reset();
bool full() const;
bool empty() const;
std::size_t size() const;
void write(int);
int read();
};
// Constructor
// Set the capacity via initializer list because it is const
CircularBuffer::CircularBuffer(std::size_t space):capacity{space}
{
u_ptr = std::unique_ptr<int[]>(new int[space]);
head = 0;
tail = 0;
full_v = false;
}
// Reset the Buffer
void CircularBuffer::reset()
{
head = 0;
tail = 0;
full_v = false;
u_ptr[head] = int{};
}
// Check if buffer is full
bool CircularBuffer::full() const
{
return full_v;
}
// Check if buffer is empty
bool CircularBuffer::empty() const
{
return (!full_v && head == tail);
}
// Return the size of the buffer
std::size_t CircularBuffer::size() const
{
if(full_v)
{
return capacity;
}
if(head >= tail)
{
return head - tail;
}
else
{
return capacity - (tail - head);
}
}
// Write values into the buffer
void CircularBuffer::write(int data)
{
u_ptr[head] = data;
head = (head + 1) % capacity;
if(full_v)
{
tail = (tail + 1) % capacity;
}
full_v = (head == tail);
}
// Read from buffer
int CircularBuffer::read()
{
if(this -> empty())
{
return int{};
}
int ret_val = u_ptr[tail];
full_v = false;
tail = (tail + 1) % capacity;
return ret_val;
}
int main()
{
CircularBuffer cb{10};
std::cout << "Empty: " << cb.empty() << "\n";
for(int i = 0; i < 10; i++)
{
cb.write(i);
}
std::cout << "Full: " << cb.full() << "\n";
std::cout << "Read: " << cb.read() << "\n";
std::cout << "Full: " << cb.full() << "\n";
std::cout << "Empty: " << cb.empty() << "\n";
std::cout << "Size: " << cb.size() << "\n";
cb.write(35);
std::cout << "Size: " << cb.size() << "\n";
std::cout << "Read: " << cb.read() << "\n";
std::cout << "Size: " << cb.size() << "\n";
cb.reset();
std::cout << "Size: " << cb.size() << "\n";
return 0;
}
Is the implementation correct? What are the shortcomings that can be fixed?
I see that the original reference uses a
mutex
object and uses lock. Is such an approach used with all data structures? If not, is there a reason why that has been used here?