diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-10-09 05:04:08 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-10-09 05:18:19 +0900 |
| commit | 87b5c30ef6d5b7b8a10d6a5a8610054c403923e6 (patch) | |
| tree | 805116c39a623bb30fc532af47ea3ed78b7304c0 /container/output.go | |
| parent | df9b77b077d967d35082adb8ab3b00dd67d7bc97 (diff) | |
message: relocate from container
This package is quite useful. This change allows it to be imported without importing container.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container/output.go')
| -rw-r--r-- | container/output.go | 77 |
1 files changed, 0 insertions, 77 deletions
diff --git a/container/output.go b/container/output.go deleted file mode 100644 index 4d799eb4..00000000 --- a/container/output.go +++ /dev/null @@ -1,77 +0,0 @@ -package container - -import ( - "bytes" - "io" - "sync" - "sync/atomic" - "syscall" -) - -const ( - suspendBufInitial = 1 << 12 - suspendBufMax = 1 << 24 -) - -// Suspendable proxies writes to a downstream [io.Writer] but optionally withholds writes -// between calls to Suspend and Resume. -type Suspendable struct { - Downstream io.Writer - - s atomic.Bool - - buf bytes.Buffer - // for growing buf - bufOnce sync.Once - // for synchronising all other buf operations - bufMu sync.Mutex - - dropped int -} - -func (s *Suspendable) Write(p []byte) (n int, err error) { - if !s.s.Load() { - return s.Downstream.Write(p) - } - s.bufOnce.Do(func() { s.buf.Grow(suspendBufInitial) }) - - s.bufMu.Lock() - defer s.bufMu.Unlock() - - if free := suspendBufMax - s.buf.Len(); free < len(p) { - // fast path - if free <= 0 { - s.dropped += len(p) - return 0, syscall.ENOMEM - } - - n, _ = s.buf.Write(p[:free]) - err = syscall.ENOMEM - s.dropped += len(p) - n - return - } - - return s.buf.Write(p) -} - -// IsSuspended returns whether [Suspendable] is currently between a call to Suspend and Resume. -func (s *Suspendable) IsSuspended() bool { return s.s.Load() } - -// Suspend causes [Suspendable] to start withholding output in its buffer. -func (s *Suspendable) Suspend() bool { return s.s.CompareAndSwap(false, true) } - -// Resume undoes the effect of Suspend and dumps the buffered into the downstream [io.Writer]. -func (s *Suspendable) Resume() (resumed bool, dropped uintptr, n int64, err error) { - if s.s.CompareAndSwap(true, false) { - s.bufMu.Lock() - defer s.bufMu.Unlock() - - resumed = true - dropped = uintptr(s.dropped) - - s.dropped = 0 - n, err = io.Copy(s.Downstream, &s.buf) - s.buf.Reset() - } - return -} |
