Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+66
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Package coalescedop provides a mechanism to serialize and coalesce
|
||||
// calls to a function. At most one call is in flight at a time, and
|
||||
// if additional calls are requested while one is running, exactly one
|
||||
// more execution is scheduled after the current one completes.
|
||||
//
|
||||
// Unlike [singleflight.Group], which deduplicates concurrent callers
|
||||
// onto a single in-flight call, [CoalescedOp] ensures that a new
|
||||
// execution occurs after the current one finishes, so changes that
|
||||
// happened during the in-flight call are picked up by the next run.
|
||||
package coalescedop
|
||||
|
||||
import "sync"
|
||||
|
||||
// CoalescedOp serializes and coalesces calls to a function.
|
||||
// At most one call is in flight at a time. If additional calls
|
||||
// are requested while one is running, exactly one more execution
|
||||
// is scheduled (not one per request).
|
||||
//
|
||||
// The zero value is not valid; use [New].
|
||||
type CoalescedOp struct {
|
||||
mu sync.Mutex
|
||||
fn func()
|
||||
running bool
|
||||
pending bool
|
||||
}
|
||||
|
||||
// New returns a CoalescedOp that calls fn.
|
||||
func New(fn func()) *CoalescedOp {
|
||||
return &CoalescedOp{fn: fn}
|
||||
}
|
||||
|
||||
// Do requests that the operation be run. If no execution is in
|
||||
// progress, a new goroutine is started to run the function. If an
|
||||
// execution is already in progress, the function will be run exactly
|
||||
// once more after the current execution completes.
|
||||
//
|
||||
// Do never blocks.
|
||||
func (c *CoalescedOp) Do() {
|
||||
c.mu.Lock()
|
||||
if c.running {
|
||||
c.pending = true
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
c.running = true
|
||||
c.mu.Unlock()
|
||||
go c.run()
|
||||
}
|
||||
|
||||
func (c *CoalescedOp) run() {
|
||||
for {
|
||||
c.fn()
|
||||
|
||||
c.mu.Lock()
|
||||
if !c.pending {
|
||||
c.running = false
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
c.pending = false
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user