61 lines
1017 B
Go
61 lines
1017 B
Go
|
// Copyright 2020 lesismal. All rights reserved.
|
||
|
// Use of this source code is governed by an MIT-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package concurrent
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
_defaultBatch = NewBatch()
|
||
|
)
|
||
|
|
||
|
type call struct {
|
||
|
mux sync.RWMutex
|
||
|
ret interface{}
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
// Batch .
|
||
|
type Batch struct {
|
||
|
_mux sync.Mutex
|
||
|
_callings map[interface{}]*call
|
||
|
}
|
||
|
|
||
|
// Do .
|
||
|
func (o *Batch) Do(key interface{}, f func() (interface{}, error)) (interface{}, error) {
|
||
|
o._mux.Lock()
|
||
|
c, ok := o._callings[key]
|
||
|
if ok {
|
||
|
o._mux.Unlock()
|
||
|
c.mux.RLock()
|
||
|
c.mux.RUnlock()
|
||
|
return c.ret, c.err
|
||
|
}
|
||
|
|
||
|
c = &call{}
|
||
|
c.mux.Lock()
|
||
|
o._callings[key] = c
|
||
|
o._mux.Unlock()
|
||
|
c.ret, c.err = f()
|
||
|
c.mux.Unlock()
|
||
|
|
||
|
o._mux.Lock()
|
||
|
delete(o._callings, key)
|
||
|
o._mux.Unlock()
|
||
|
|
||
|
return c.ret, c.err
|
||
|
}
|
||
|
|
||
|
// NewBatch .
|
||
|
func NewBatch() *Batch {
|
||
|
return &Batch{_callings: map[interface{}]*call{}}
|
||
|
}
|
||
|
|
||
|
// Do .
|
||
|
func Do(key interface{}, f func() (interface{}, error)) (interface{}, error) {
|
||
|
return _defaultBatch.Do(key, f)
|
||
|
}
|