diff options
| author | 2025-10-17 17:36:24 +0200 | |
|---|---|---|
| committer | 2025-11-17 14:11:11 +0100 | |
| commit | f714b06fec5b93cf076d0f92eeb8aa7c32cfb531 (patch) | |
| tree | 8e1a89dd7b0db0f17b695557d03eede9055134ae /vendor/codeberg.org/gruf/go-runners/process.go | |
| parent | [bugfix] recheck for just-processed-emoji within mutex lock before starting p... (diff) | |
| download | gotosocial-f714b06fec5b93cf076d0f92eeb8aa7c32cfb531.tar.xz | |
[chore] update dependencies (#4507)
- codeberg.org/gruf/go-runners: v1.6.3 -> v1.7.0
- codeberg.org/gruf/go-sched: v1.2.4 -> v1.3.0
- github.com/tdewolff/minify/v2: v2.24.3 -> v2.24.4
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4507
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-runners/process.go')
| -rw-r--r-- | vendor/codeberg.org/gruf/go-runners/process.go | 116 |
1 files changed, 54 insertions, 62 deletions
diff --git a/vendor/codeberg.org/gruf/go-runners/process.go b/vendor/codeberg.org/gruf/go-runners/process.go index ca39ac0d0..3feeff258 100644 --- a/vendor/codeberg.org/gruf/go-runners/process.go +++ b/vendor/codeberg.org/gruf/go-runners/process.go @@ -2,80 +2,72 @@ package runners import ( "fmt" + "unsafe" + "sync" ) -// Processable defines a runnable process with error return -// that can be passed to a Processor instance for managed running. -type Processable func() error - // Processor acts similarly to a sync.Once object, except that it is reusable. After // the first call to Process(), any further calls before this first has returned will // block until the first call has returned, and return the same error. This ensures // that only a single instance of it is ever running at any one time. -type Processor struct { - mutex sync.Mutex - wait *sync.WaitGroup - err *error -} +type Processor struct{ p atomic_pointer } // Process will process the given function if first-call, else blocking until // the first function has returned, returning the same error result. -func (p *Processor) Process(proc Processable) (err error) { - // Acquire state lock. - p.mutex.Lock() - - if p.wait != nil { - // Already running. - // - // Get current ptrs. - waitPtr := p.wait - errPtr := p.err - - // Free state lock. - p.mutex.Unlock() - - // Wait for finish. - waitPtr.Wait() - return *errPtr - } - - // Alloc waiter for new process. - var wait sync.WaitGroup - - // No need to alloc new error as - // we use the alloc'd named error - // return required for panic handling. - - // Reset ptrs. - p.wait = &wait - p.err = &err - - // Set started. - wait.Add(1) - p.mutex.Unlock() - - defer func() { - if r := recover(); r != nil { - if err != nil { - rOld := r // wrap the panic so we don't lose existing returned error - r = fmt.Errorf("panic occured after error %q: %v", err.Error(), rOld) - } - - // Catch any panics and wrap as error. - err = fmt.Errorf("caught panic: %v", r) +func (p *Processor) Process(proc func() error) (err error) { + var i *proc_instance + + for { + // Attempt to load existing instance. + ptr := (*proc_instance)(p.p.Load()) + if ptr != nil { + + // Wait on existing. + ptr.wait.Wait() + err = ptr.err + return } - // Mark done. - wait.Done() + if i == nil { + // Allocate instance. + i = new(proc_instance) + i.wait.Add(1) + } - // Set stopped. - p.mutex.Lock() - p.wait = nil - p.mutex.Unlock() - }() + // Try to acquire start slot by + // setting ptr to *our* instance. + if p.p.CAS(nil, unsafe.Pointer(i)) { + defer func() { + if r := recover(); r != nil { + if i.err != nil { + rOld := r // wrap the panic so we don't lose existing returned error + r = fmt.Errorf("panic occured after error %q: %v", i.err.Error(), rOld) + } + + // Catch panics and wrap as error return. + i.err = fmt.Errorf("caught panic: %v", r) + } + + // Set return. + err = i.err + + // Release the + // goroutines. + i.wait.Done() + + // Free processor. + p.p.Store(nil) + }() + + // Run func. + i.err = proc() + return + } + } +} - // Run process. - err = proc() - return +type proc_instance struct { + wait sync.WaitGroup + err error } |
