簡體   English   中英

循環緩沖區的實現

[英]circular buffer implementation

再次是,我再次提出了非常簡單的實現,如下所示:

    // write data always! if buffer is already full, overwrite old data!
    void Put( const CONTENT_TYPE &data )
    {
        buffer[ inOffset++] = data;
        inOffset%=size;

        // was data overwritten, skip it by increment read offset
        if ( inOffset == outOffset ) 
        {
            outOffset++;
            outOffset%=size;
            std::cout << "Overwrite" << std::endl;
        }
    }

    CONTENT_TYPE Pull()
    {
        CONTENT_TYPE data = buffer[ outOffset++ ];
        outOffset %= size;
        return data;
    }

但是,這種簡單的算法僅利用大小為1的緩沖區元素!

如果我想避免這種情況,我只找到了添加另一個計數器變量的解決方案,這浪費了我sizeof(counter_var)-sizeof(element)個字節。

問:有沒有不浪費內存的解決方案? 它看起來很簡單,但我抓不到:-)

備注:還有更多的代碼行可以保護空讀取和其他內容,但這對這個問題並不重要。 而且它沒有被標記為c ++,因為該算法不依賴於語言,即使我舉一個c ++代碼示例也是如此。

您可以使用兩個整數並填充所有插槽(如果一個是索引,另一個是元素計數),然后立即進行轉換以找到第二個索引:

void put(const ELEMENT& element) {
  if (nElements == size) throw "put: buffer full";
  buffer[(start + nElements++) % size] = element;
}

ELEMENT get() {
  if (nElements == 0) throw "get: buffer empty";
  ELEMENT& value = buffer[start];
  start = (start + 1) % size;
  --nElements;
  return value;
}

當然,您可以用if (foo > size) foo -= size;替換mod操作if (foo > size) foo -= size; 如果你喜歡。

您可以通過使用不同的時間點進行模運算來解決這個問題。 假設我們在每次訪問后都增加了讀寫指針。 如果現在我們在增加之后立即執行讀指針的模,而就在讀之前立即寫寫指針的模,則| write-read | 完整緩沖區的長度將是緩沖區的長度,無需任何特殊情況處理。 為此,您的寫指針應始終使用 % buffer_length ,但應存儲 % (2 * buffer_length)

我不特別喜歡Mark的答案,因為按特殊情況處理事物通常不是一個好主意,在您通常使用size_t (即無符號整數)的地方,引入負的前哨值就少了。

您可以對偏移量之一使用特殊的前哨值,例如-1,以指示緩沖區已滿或為空。 這會使檢查和修改偏移量的代碼復雜化。

// write data always! if buffer is already full, overwrite old data!
void Put( const CONTENT_TYPE &data )
{
    buffer[ inOffset++] = data;
    inOffset%=size;

    // was data overwritten, skip it by setting read offset to sentinel
    if ( inOffset == outOffset || outOffset == -1 ) 
    {
        outOffset = -1;
        std::cout << "Overwrite" << std::endl;
    }
}

CONTENT_TYPE Pull()
{
    if (outOffset == -1)
        outOffset = inOffset;
    CONTENT_TYPE data = buffer[ outOffset++ ];
    outOffset %= size;
    return data;
}

bool IsEmpty()
{
    return outOffset == inOffset;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM