У меня есть кольцевой буфер, размер которого равен 2. Моя цель — оптимизировать его работу. Вот краткий код:
class CircularBuffer
{
public:
CircularBuffer(unsigned int bufferSize); // align this size to power of 2
void read(char * dst, unsigned int bytes);
void write(char * src, unsigned int bytes);
private:
unsigned int m_readOffset;
unsigned int m_writeOffset;
std::vector<char> m_buffer;
};
CircularBuffer::write(char * src, unsigned int bytes)
{
int dif = bytes - (m_buffer.size() - m_writeOffset);
unsigned int mask = ~(dif >> 31); // 0 or 0xFFFFFFFF
dif &= mask; // now i know how much bytes i need to put at the beginning of the buffer
memcpy(&m_buffer[m_writeOffset], src, bytes - dif);
memcpy(&m_buffer[0], src + bytes - dif, dif);
m_writeOffset = (m_wirteffset + bytes) & (m_buffer.size() -1);
}
m_writeOffset
указывает, сколько байтов уже помещено в буфер.
Как вы можете видеть, я избавляюсь от условий вроде < srcSize) и т. д., и вычислить writeOffset с помощью битовой маски.
Но мой ведущий программист говорит мне, что есть способ подсчитать, сколько байтов поместить в конец буфера и сколько байтов поместить в начало, используя побитовые операции, потому что размер буфера равен степени 2. Есть предложения?
Вы уже используете переменные без знака для отслеживания передней и задней частей вашей очереди (это хорошо); просто увеличить m_writeOffset
на каждой операции записи (постановки в очередь) и приращения m_readOffset
на каждой операции чтения (удаления из очереди). Вычислить оставшееся количество элементов буфера так же просто, как:
// returns the distance between m_readOffset and m_writeOffset
// (the count of the actual buffer elements):
uint32_t CircularBuffer::Size()
{
if (m_readOffset < m_writeOffset)
{
return (m_writeOffset - m_readOffset);
}
else
{
return (m_readOffset - m_writeOffset);
}
}
Посмотрите исходный код моей реализации шаблона STL циклической очереди base-2:
Других решений пока нет …