I am currently working on a threadsafe circular buffer for storing pointers. As basis I used the code from this thread: Thread safe implementation of circular buffer. My code is shown below.
Because I want to store pointers in the circular buffer, I need to make sure that allocated memory is deleted, in case the buffer is full and the first element is overwritten, as mentioned in the boost documentation:
When a circular_buffer becomes full, further insertion will overwrite the stored pointers - resulting in a memory leak. 1
So I tried to delete the first element in the add method, in case the buffer is full and the type T of the template is actually a pointer. This leads to a C2541-error, because I try to delete an object, which is not seen as a pointer.
Is my basic approach correct? How can I solve the above issue?
#pragma once
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/circular_buffer.hpp>
#include <type_traits>
#include "Settings.hpp"
template <typename T>
class thread_safe_circular_buffer : private boost::noncopyable
{
public:
typedef boost::mutex::scoped_lock lock;
thread_safe_circular_buffer(bool *stop) : stop(stop) {}
thread_safe_circular_buffer(int n, bool *stop) : stop(stop) {cb.set_capacity(n);}
void add (T imdata) {
monitor.lock();
std::cout << "Buffer - Add Enter, Size: " << cb.size() << "\n";
if(cb.full())
{
std::cout << "Buffer - Add Full.\n";
T temp = cb.front();
if(std::is_pointer<T>::value)
delete[] temp;
}
std::cout << "Buffer - Push.\n";
cb.push_back(imdata);
monitor.unlock();
std::cout << "Buffer - Add Exit.\n";
}
T get() {
std::cout << "Buffer - Get Enter, Size: " << cb.size() << "\n";
monitor.lock();
while (cb.empty())
{
std::cout << "Buffer - Get Empty, Size: " << cb.size() << "\n";
monitor.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if(*stop)
return NULL;
monitor.lock();
}
T imdata = cb.front();
// Remove first element of buffer
std::cout << "Buffer - Pop.\n";
cb.pop_front();
monitor.unlock();
std::cout << "Buffer - Get Exit.\n";
return imdata;
}
void clear() {
lock lk(monitor);
cb.clear();
}
int size() {
lock lk(monitor);
return cb.size();
}
void set_capacity(int capacity) {
lock lk(monitor);
cb.set_capacity(capacity);
}
bool *stop;
private:
boost::condition buffer_not_empty;
boost::mutex monitor;
boost::circular_buffer<T> cb;
};