diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-02-16 17:26:09 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-02-16 18:51:53 +0900 |
| commit | e599b5583dd821ed26bdfc01f7f67d4a317b9843 (patch) | |
| tree | b444a3dc964814360e6779bc10b30f2e599b537c /internal/fmsg/defer.go | |
| parent | 33a4ab11c226c736c0d8b2644fbbe27a5ca045e9 (diff) | |
fmsg: implement suspend in writer
This removes the requirement to call fmsg.Exit on every exit path, and enables direct use of the "log" package. However, fmsg.BeforeExit is still encouraged when possible to catch exit on suspended output.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/fmsg/defer.go')
| -rw-r--r-- | internal/fmsg/defer.go | 98 |
1 files changed, 0 insertions, 98 deletions
diff --git a/internal/fmsg/defer.go b/internal/fmsg/defer.go deleted file mode 100644 index 677f5ceb..00000000 --- a/internal/fmsg/defer.go +++ /dev/null @@ -1,98 +0,0 @@ -package fmsg - -import ( - "os" - "sync" - "sync/atomic" -) - -var ( - wstate atomic.Bool - dropped atomic.Uint64 - withhold = make(chan struct{}, 1) - msgbuf = make(chan dOp, 64) // these ops are tiny so a large buffer is allocated for withholding output - - dequeueOnce sync.Once - queueSync sync.WaitGroup -) - -func dequeue() { - go func() { - for { - select { - case op := <-msgbuf: - op.Do() - queueSync.Done() - case <-withhold: - <-withhold - } - } - }() -} - -// queue submits ops to msgbuf but drops messages -// when the buffer is full and dequeue is withholding -func queue(op dOp) { - queueSync.Add(1) - - select { - case msgbuf <- op: - default: - // send the op anyway if not withholding - // as dequeue will get to it eventually - if !wstate.Load() { - msgbuf <- op - } else { - queueSync.Done() - // increment dropped message count - dropped.Add(1) - } - } -} - -type dOp interface{ Do() } - -func Exit(code int) { - Resume() // resume here to avoid deadlock - queueSync.Wait() - os.Exit(code) -} - -func Suspend() { - dequeueOnce.Do(dequeue) - if wstate.CompareAndSwap(false, true) { - queueSync.Wait() - withhold <- struct{}{} - } -} - -func Resume() { - dequeueOnce.Do(dequeue) - if wstate.CompareAndSwap(true, false) { - withhold <- struct{}{} - if d := dropped.Swap(0); d != 0 { - Printf("dropped %d messages during withhold", d) - } - } -} - -type dPrint []any - -func (v dPrint) Do() { - std.Print(v...) -} - -type dPrintf struct { - format string - v []any -} - -func (d *dPrintf) Do() { - std.Printf(d.format, d.v...) -} - -type dPrintln []any - -func (v dPrintln) Do() { - std.Println(v...) -} |
