Я пытаюсь реализовать циклический буфер, который использует мьютекс, чтобы быть потокобезопасным. Я использовал следующий код:
#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() для указания этого массива, но это тоже не сработало). Извините, если этот вопрос немного абстрактен, я, честно говоря, полностью запутался в этом вопросе (первая работа в качестве разработчика и буквально мои 6 дней работы, они заставили меня сделать очень сложное приложение для радиолокационной карты). Дайте мне знать, если вам нужны какие-либо разъяснения по чему-либо.
редактировать: Спасибо всем! Ответ Майкла сработал, и спасибо за предложения. Честно говоря, я чувствую, что прямо сейчас тону над головой, поэтому все советы чрезвычайно полезны!
size
,empty
,full
), которые также требуют блокировки - вы не можете получить доступ к этим переменным потокобезопасным способом без блокировки (или каким-то образом сделать их атомарными). Помните, когда вы добавляете блокировки, что вызовget
кempty
не должен блокироваться во второй раз - вам, вероятно, нужен частныйempty_no_lock()
, который вызываетget
, который не добавляет блокировку. - person Mike Vine   schedule 09.05.2019