~/problems / Pools & pipelines / Ring buffers and producer/consumer pipelines

Overwriting byte ring buffer with UTF-8 text

medium 2 levels ~45 min

Level 1 A byte ring buffer that overwrites

Build RingBuffer(capacity): a fixed block of capacity bytes with a write position and a read position that move forward independently and wrap around. Writing never blocks or fails: if the writer laps the reader, the oldest unread bytes are silently overwritten.

  • write(data: bytes) -> None: append all of data. If that makes more than capacity bytes unread, the oldest unread bytes are lost (overwritten), so at most capacity unread bytes remain: the last capacity bytes ever written. (A single write longer than capacity keeps only its own tail.)
  • read(n: int) -> bytes: remove and return up to n of the oldest unread bytes (fewer, possibly b"", if fewer are unread).
  • available() -> int: how many unread bytes there are.
  • dropped() -> int: the total number of bytes that were overwritten before anyone read them.
rb = RingBuffer(5)
rb.write(b"abc")
rb.read(2)          # b"ab"
rb.write(b"defgh")  # unread would be "cdefgh" (6 > 5): "c" is overwritten
rb.available()      # 5
rb.dropped()        # 1
rb.read(10)         # b"defgh"
rb.write(b"123456789")
rb.read(10)         # b"56789"     (dropped() is now 5)

Constraints: 1 <= capacity <= 2^20. The buffer is used for streaming, so each call must cost O(len(data)) or O(n), not O(capacity): no rebuilding or shifting the whole buffer per call.

Show hint

Keep a bytearray(capacity) and two ever-increasing counters, written and read_pos (total bytes ever written / consumed). A byte's slot is position % capacity, so a write or read is at most two slice copies (before and after the wrap). After a write, if written - read_pos > capacity, move read_pos up to written - capacity and add the difference to dropped.

Level 2 unlocks when level 1 passes.

Topic: Ring buffers and producer/consumer pipelines. Fixed-size circular buffers, head/tail indexes, back-pressure.

0:00
Ctrl ' run · Ctrl ↵ submit
esc