我目前正在研究一个用于存储指针的线程安全循环缓冲区。作为基础,我使用了此线程中的代码:Thread safe implementation of circular buffer。我的代码如下所示。
因为我想在循环缓冲区中存储指针,所以我需要确保删除已分配的内存,以防缓冲区已满并且第一个元素被覆盖,如boost文档中所述:
当circular_buffer变满时,进一步插入将覆盖存储的指针 - 导致内存泄漏。 1
所以我尝试删除add方法中的第一个元素,以防缓冲区已满并且模板的类型T实际上是指针。这会导致C2541错误,因为我尝试删除一个不被视为指针的对象。
我的基本方法是否正确?我该如何解决上述问题?
#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;
};
答案 0 :(得分:2)
错误告诉您问题:您无法删除不是指针的内容。当T
不是指针类型时,delete[] temp;
没有意义。如果你的缓冲区存储的内容没有被new[]
分配,或者你的循环缓冲区在概念上没有“拥有”,那么这也是一个坏主意。指针。
我想你可能会误解整个问题。升级文档中的警告仅适用于您无法承受“失败”的情况。存储在缓冲区中的任何数据。这是一个问题的一个例子 - 他们特别强调的一个例子 - 是你在缓冲区中存储原始指针,它们是你对动态分配的内存的唯一引用。
我认为,只有三种合理的设计:
circular_buffer<unique_ptr<T[]>>
用于存储动态分配的数组)。因此,让您的课程不必担心如何处理丢失的数据。答案 1 :(得分:1)
按照提升的方式做:让代码的用户处理这个问题。如果存储了对象,它的析构函数应该处理可能的内存管理,如果指针存储,你无法知道它实际指向的内容:数组,对象,需要释放的内存,在别处管理的内存,而不是动态内存