Open5

miniio: リングバッファの実装

okuokuokuoku

手動でリングバッファを実装するとか何年ぶりだよ。。という感じなので図を書いて整理。。

リングバッファの構成

リングバッファ...といっても、実際のメモリは環状にできないのでポインタの集合で表現することになる。

  • len - リングバッファ全体のサイズ
  • readptr - リングバッファの読み取りポインタ
  • writeptr - リングバッファの書き込みポインタ

今回の場合は、オーバーフローは発生させないと仮定してよい。

okuokuokuoku

readptr < writeptr (ただし writeptr != len )ケース

これはtrivial。

  • write側: len - writeptr のサイズまで一度に書き出せる。
  • read側: writeptr - readptr のサイズのデータが読める。
okuokuokuoku

writeptr == len ケース

既に読み終わっているところにデータが書けるケース。

  • write側: readptr のサイズまで一度に書き出せる
  • read側: len - readptr のサイズのデータが読める

readptr == 0 ケース

自然に、 readptr == 0であればバッファが満杯のケースと言える。(場合分けは不要だが、このタイミングでのゼロ長のwriteには注意が必要 -- 後述)

okuokuokuoku

writeptr < readptr ケース

バッファの途中に書けるケース。

  • write側: readptr - writeptr のサイズまで一度に書き出せる
  • read側: len - (readptr - writeptr) のサイズのデータが読み出せる
okuokuokuoku

writeptr == readptr ケース

これだけ場合分けが必要。

readptr == writeptr == 0 の場合

このケースは、バッファが空っぽであることを表現する。 場合分けが必要 。つまり、 読み取りによって readptr == writeptr となった場合はゼロにリセットする と約束する必要がある。

readptr != 0 の場合

このケースでは、バッファがいっぱいであることを表現する。↑の場合分けを実現するため、 ゼロ長のwriteではポインタを更新しない と約束する必要がある。そうしないと、 readptr == 0、 writeptr == len のときにゼロ長の書き込みをすると readptr == writeptr == 0 になってしまう。