From 988afc063c01c7e57afdd4ce15904dee876a2fc0 Mon Sep 17 00:00:00 2001 From: Martin Gysel Date: Thu, 2 Jul 2026 15:20:26 +0200 Subject: [PATCH] add option to not error in case of a timeout in some use cases (e.g. emulating a serial port read with timeout) it may be useful to not go into error if a read and/or write timeout occurs. Signed-off-by: Martin Gysel --- ring_buffer.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ring_buffer.go b/ring_buffer.go index c617ffb..ce9af00 100644 --- a/ring_buffer.go +++ b/ring_buffer.go @@ -54,6 +54,7 @@ type RingBuffer struct { overwrite bool // when true, overwrite old data when buffer is full rTimeout time.Duration // Applies to writes (waits for the read condition) wTimeout time.Duration // Applies to read (wait for the write condition) + noClOnTo bool // do not set buffer in error on a timeout mu sync.Mutex wg sync.WaitGroup readCond *sync.Cond // Signaled when data has been read. @@ -151,6 +152,18 @@ func (r *RingBuffer) WithWriteTimeout(d time.Duration) *RingBuffer { return r } +// WithNoCloseOnTimeout will set the ringbuffer to not close on timeout. +// By default, the ringbuffer will close on timeout and return context.DeadlineExceeded. +// When this option is set, the ringbuffer will not close on timeout (but still return +// context.DeadlineExceeded) and will continue to operate. +// This is useful when you want to handle timeouts without closing the ringbuffer. +func (r *RingBuffer) WithNoCloseOnTimeout() *RingBuffer { + r.mu.Lock() + r.noClOnTo = true + r.mu.Unlock() + return r +} + func (r *RingBuffer) setErr(err error, locked bool) error { if !locked { r.mu.Lock() @@ -319,7 +332,9 @@ func (r *RingBuffer) waitRead() (ok bool) { r.readCond.Wait() if time.Since(start) >= r.rTimeout { - r.setErr(context.DeadlineExceeded, true) //nolint errcheck + if !r.noClOnTo { + r.setErr(context.DeadlineExceeded, true) //nolint errcheck + } return false } return true @@ -440,7 +455,9 @@ func (r *RingBuffer) waitWrite() (ok bool) { r.writeCond.Wait() if time.Since(start) >= r.wTimeout { - r.setErr(context.DeadlineExceeded, true) //nolint errcheck + if !r.noClOnTo { + r.setErr(context.DeadlineExceeded, true) //nolint errcheck + } return false } return true