我正在尝试实现一个利用互斥量的循环缓冲区,以确保线程安全。我一直在使用以下代码:
#include <cstdio>
#include <memory>
#include <mutex>
template <class T>
class circular_buffer {
public:
explicit circular_buffer(size_t size) :
buf_(std::unique_ptr<T[]>(new T[size])),
max_size_(size)
{
}
void put(T item)
{
std::lock_guard<std::mutex> lock(mutex_);
buf_[head_] = item;
if (full_)
{
tail_ = (tail_ + 1) % max_size_;
}
head_ = (head_ + 1) % max_size_;
full_ = head_ == tail_;
}
T get()
{
std::lock_guard<std::mutex> lock(mutex_);
if (empty())
{
return T();
}
//Read data and advance the tail (we now have a free space)
auto val = buf_[tail_];
full_ = false;
tail_ = (tail_ + 1) % max_size_;
return val;
}
void reset()
{
std::lock_guard<std::mutex> lock(mutex_);
head_ = tail_;
full_ = false;
}
bool empty() const
{
//if head and tail are equal, we are empty
return (!full_ && (head_ == tail_));
}
bool full() const
{
//If tail is ahead the head by 1, we are full
return full_;
}
size_t capacity() const
{
return max_size_;
}
size_t size() const
{
size_t size = max_size_;
if (!full_)
{
if (head_ >= tail_)
{
size = head_ - tail_;
}
else
{
size = max_size_ + head_ - tail_;
}
}
return size;
}
private:
std::mutex mutex_;
std::unique_ptr<T[]> buf_;
size_t head_ = 0;
size_t tail_ = 0;
const size_t max_size_;
bool full_ = 0;
};
此代码的问题是,我似乎无法使它与浮点数数组一起使用。我得到一个函数返回数组错误(从get函数)。我不完全确定如何解决此问题(尝试传入数组并使用get()函数指向该数组,但这也不起作用)。抱歉,如果这个问题有点抽象,那么我真的完全不愿意(我是开发人员的第一份工作,实际上是我工作了6天,他们让我开发了一个非常复杂的雷达绘图应用程序)。让我知道您是否需要任何澄清。
edit:谢谢大家!迈克尔的回答很奏效,感谢您的建议。老实说,我现在好像被淹死了,所以所有提示都非常有用!
答案 0 :(得分:4)
首先,请注意,如果有人同时使用此类模板的实例的size()
,empty()
或full()
方法,而其他人同时使用{{1} },get()
或put()
,最终将导致未定义的行为。 reset()
或size()
也将必须锁定互斥锁,因为它们读取可能被修改的对象(empty()
,full_
和head_
)的值同时。除此之外,在我看来tail_
总是写一些东西,即使队列已满。那可能不是人们通常想要的。
根据您的描述,我认为您要询问的问题与尝试创建put()
有关。考虑一下如果将circular_buffer<float[4]>
的类型替换为get()
,float[4]
方法会变成什么:
T
最后得到一个返回数组的函数。函数不允许返回数组[dcl.fct]/11。*这就是为什么一旦在这样的float get()[4] { … }
上调用get()
方法就会导致编译器错误的原因。使用例如std::array
代替:circular_buffer
。
*)我认为这很可能是出于历史原因。数组类型被设计为在传递给C中的函数时表现的方式是,使得数组最终有效地被引用传递。函数没有按引用返回数组的好方法,而按值返回将与它们的传递方式不一致。因此,最好是根本不允许返回数组……