У меня есть очередь производителей-потребителей, которая обновляется параллельными программами. Очередь запрашивается для различных статистических данных, таких как среднее или стандартное отклонение или дисперсия, или что-то еще в текущем содержимом очереди. Для среднего значения, это код, я используюЭффективная общая очередь буферов для последовательной обработки
class BufferQueue {
const int nMaxQueueSize_;
int* values;
int head, tail;
double sum;
::utils::FastMutex queue_mutex;
public:
BufferQueue(const int nMaxQueueSize) :
nMaxQueueSize_(nMaxQueueSize) {
head = tail = 0;
sum = 0;
values = new int[nMaxQueueSize_];
}
void enqueue(int val) {
values[head] = val;
if ((head + 1) % nMaxQueueSize_ == tail) {
queue_mutex.lock();
sum = val.value_point - values[tail].value_point;
utils::memory_barrier();
head = (1 + head) % nMaxQueueSize_;
tail = (1 + tail) % nMaxQueueSize_;
queue_mutex.unlock();
} else {
queue_mutex.lock();
sum += val.value_point;
utils::memory_barrier();
head = (1 + head) % nMaxQueueSize_;
queue_mutex.unlock();
}
}
bool dequeue() {
if (head != tail) {
queue_mutex.lock();
sum -= values[tail].value_point;
utils::memory_barrier();
tail = (1 + tail) % nMaxQueueSize_;
queue_mutex.unlock();
return true;
} else {
sum = 0;
return false;
}
}
MarketSpreadPoint& operator[](int i) {
return values[ (tail + i) % nMaxQueueSize_ ];
}
inline int getSize() {
return (head - tail + nMaxQueueSize_) % nMaxQueueSize_;
}
inline double average() {
queue_mutex.lock();
double result = sum/getSize();
queue_mutex.unlock();
return result;
}
~BufferQueue() {
delete values;
}
};
ПРИМЕЧАНИЕ: Одна важная вещь, чтобы помнить о том, что только одна операция выполняется. Я тоже не хочу повторять код, записи отдельных реализаций как BufferQueueAverage, BufferQueueVariance и т.д. Я хочу очень предел кода избыточности (оптимизации компилятора). Даже кондиционирование по типу очереди для каждого обновления кажется субоптимальным.
inline double average() {
queue_mutex.lock();
if(type_is_average){
double result = sum/getSize();
}else if(type_is_variance){
/// update accordingly.
}
double result = sum/getSize();
queue_mutex.unlock();
return result;
}
Что может быть хорошей альтернативой этой идее?
Примечание: В этом варианте осуществления, если очередь полна, голова автоматически сделать хвост, чтобы двигаться вперед. Другими словами, самый старый элемент удаляется автоматически.
Thanks
что такое, что 'ИНТ * значение = новый MarketSpreadPoint [nMaxQueueSize _];' –
@D? ieterLücking, извините, исправлено – v78
Ваша очередь не является потокобезопасной. Я говорю это, потому что ваш код выглядит так, как будто вы пытаетесь сделать это, но он ошибочен. Условия «enqueue» и «dequeue» имеют условия гонки. – Smeeheey