Skip to content

Instantly share code, notes, and snippets.

@afeinberg
Created September 3, 2011 20:02
Show Gist options
  • Save afeinberg/1191700 to your computer and use it in GitHub Desktop.
Save afeinberg/1191700 to your computer and use it in GitHub Desktop.
#include <stdexcept>
#include <iostream>
#include "circular_buffer.h"
/*
Valgrind output:
alex@mars:~/dev/circular-buffer$ valgrind --leak-check=yes ./circular_buffer_test
==21141== Memcheck, a memory error detector
==21141== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==21141== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==21141== Command: ./circular_buffer_test
==21141==
TestEmpty...Passed!
TestBuffer...Passed!
==21141==
==21141== HEAP SUMMARY:
==21141== in use at exit: 0 bytes in 0 blocks
==21141== total heap usage: 4 allocs, 4 frees, 208 bytes allocated
==21141==
==21141== All heap blocks were freed -- no leaks are possible
==21141==
==21141== For counts of detected and suppressed errors, rerun with: -v
==21141== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
*/
using af::CircularBuffer;
static const int capacity_ = 16;
static CircularBuffer<int>* buff_;
struct AssertionFailed: std::exception {
char const* what() const throw() {
return "assertion failed!";
}
};
#define TEST_ASSERT TestAssert
static inline void TestAssert(bool assertion, const char *msg) {
if (!assertion) {
std::cerr << msg << std::endl;
throw AssertionFailed();
}
}
static inline void Setup() {
buff_ = new CircularBuffer<int>(capacity_);
}
static inline void Teardown() {
delete buff_;
}
static inline void RunTest(const char *name, void (*test) (void)) {
std::cout << name << "...";
Setup();
try {
test();
std::cout << "Passed!";
} catch (AssertionFailed const& e) {
std::cout << "Failed!";
}
std::cout << std::endl;
Teardown();
}
void TestEmpty() {
TEST_ASSERT(buff_->IsEmpty(), "empty buffer is empty");
buff_->PushBack(1);
TEST_ASSERT(buff_->IsEmpty() == false, "not empty buffer is not empty");
}
void TestBuffer() {
int front;
int i;
// Basic Tests
TEST_ASSERT(buff_->Front(front) == false, "Front() on an empty buffer is false");
buff_->PushBack(123);
TEST_ASSERT(buff_->Front(front) == true, "Front() on buffer with elt is true");
TEST_ASSERT(front == 123, "front is correct");
TEST_ASSERT(buff_->PopFront() == true, "PopFront() is true when buffer has elts");
TEST_ASSERT(buff_->PopFront() == false, "PopFront() is false when buffer empty");
// Fill the buffer
for (i = 0; i < capacity_ + capacity_ / 2; ++i) {
buff_->PushBack(i);
}
TEST_ASSERT(buff_->Front(front) == true, "buffer overflows #1");
TEST_ASSERT(front == capacity_, "buffer overflows #2");
}
int main(int argc, char **argv) {
RunTest("TestEmpty", TestEmpty);
RunTest("TestBuffer", TestBuffer);
return 0;
}
#ifndef CIRCULAR_BUFFER_H_
#define CIRCULAR_BUFFER_H_
#include <cstdlib>
#include <cassert>
namespace af {
template<typename T>
class CircularBuffer {
public:
explicit CircularBuffer(size_t size);
virtual ~CircularBuffer();
void PushBack(const T& t);
bool IsEmpty() const;
bool PopFront();
bool Front(T& t) const;
private:
size_t write_idx_;
size_t read_idx_;
size_t size_;
T* buffer_;
};
template<typename T>
CircularBuffer<T>::CircularBuffer(size_t size)
: write_idx_(0),
read_idx_(0),
size_(size) {
buffer_ = static_cast<T*>(calloc(size_, sizeof(T)));
assert(buffer_ != NULL);
}
template<typename T>
CircularBuffer<T>::~CircularBuffer() {
free(buffer_);
}
template<typename T>
void CircularBuffer<T>::PushBack(const T& t) {
T* new_t = new (&buffer_[write_idx_]) T;
*new_t = t;
write_idx_++;
write_idx_ %= size_;
}
template<typename T>
inline bool CircularBuffer<T>::IsEmpty() const {
return read_idx_ == write_idx_;
}
template<typename T>
bool CircularBuffer<T>::PopFront() {
bool ret = false;
if (!IsEmpty()) {
ret = true;
read_idx_++;
read_idx_ %= size_;
}
return ret;
}
template<typename T>
bool CircularBuffer<T>::Front(T &t) const {
bool ret = false;
if (!IsEmpty()) {
ret = true;
t = buffer_[read_idx_];
}
return ret;
}
}
#endif // CIRCULAR_BUFFER_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment