aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/output.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-10-09 05:04:08 +0900
committerOphestra <cat@gensokyo.uk>2025-10-09 05:18:19 +0900
commit87b5c30ef6d5b7b8a10d6a5a8610054c403923e6 (patch)
tree805116c39a623bb30fc532af47ea3ed78b7304c0 /container/output.go
parentdf9b77b077d967d35082adb8ab3b00dd67d7bc97 (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.go77
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
-}