fix golint issues in core/syncx (#526)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
|
// RefreshCpu returns cpu usage, always returns 0 on systems other than linux.
|
||||||
func RefreshCpu() uint64 {
|
func RefreshCpu() uint64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,22 @@ package syncx
|
|||||||
|
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
|
|
||||||
|
// An AtomicBool is an atomic implementation for boolean values.
|
||||||
type AtomicBool uint32
|
type AtomicBool uint32
|
||||||
|
|
||||||
|
// NewAtomicBool returns an AtomicBool.
|
||||||
func NewAtomicBool() *AtomicBool {
|
func NewAtomicBool() *AtomicBool {
|
||||||
return new(AtomicBool)
|
return new(AtomicBool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForAtomicBool returns an AtomicBool with given val.
|
||||||
func ForAtomicBool(val bool) *AtomicBool {
|
func ForAtomicBool(val bool) *AtomicBool {
|
||||||
b := NewAtomicBool()
|
b := NewAtomicBool()
|
||||||
b.Set(val)
|
b.Set(val)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompareAndSwap compares current value with given old, if equals, set to given val.
|
||||||
func (b *AtomicBool) CompareAndSwap(old, val bool) bool {
|
func (b *AtomicBool) CompareAndSwap(old, val bool) bool {
|
||||||
var ov, nv uint32
|
var ov, nv uint32
|
||||||
if old {
|
if old {
|
||||||
@@ -25,6 +29,7 @@ func (b *AtomicBool) CompareAndSwap(old, val bool) bool {
|
|||||||
return atomic.CompareAndSwapUint32((*uint32)(b), ov, nv)
|
return atomic.CompareAndSwapUint32((*uint32)(b), ov, nv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets the value to v.
|
||||||
func (b *AtomicBool) Set(v bool) {
|
func (b *AtomicBool) Set(v bool) {
|
||||||
if v {
|
if v {
|
||||||
atomic.StoreUint32((*uint32)(b), 1)
|
atomic.StoreUint32((*uint32)(b), 1)
|
||||||
@@ -33,6 +38,7 @@ func (b *AtomicBool) Set(v bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// True returns true if current value is true.
|
||||||
func (b *AtomicBool) True() bool {
|
func (b *AtomicBool) True() bool {
|
||||||
return atomic.LoadUint32((*uint32)(b)) == 1
|
return atomic.LoadUint32((*uint32)(b)) == 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,32 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// An AtomicDuration is an implementation of atomic duration.
|
||||||
type AtomicDuration int64
|
type AtomicDuration int64
|
||||||
|
|
||||||
|
// NewAtomicDuration returns an AtomicDuration.
|
||||||
func NewAtomicDuration() *AtomicDuration {
|
func NewAtomicDuration() *AtomicDuration {
|
||||||
return new(AtomicDuration)
|
return new(AtomicDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForAtomicDuration returns an AtomicDuration with given value.
|
||||||
func ForAtomicDuration(val time.Duration) *AtomicDuration {
|
func ForAtomicDuration(val time.Duration) *AtomicDuration {
|
||||||
d := NewAtomicDuration()
|
d := NewAtomicDuration()
|
||||||
d.Set(val)
|
d.Set(val)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompareAndSwap compares current value with old, if equals, set the value to val.
|
||||||
func (d *AtomicDuration) CompareAndSwap(old, val time.Duration) bool {
|
func (d *AtomicDuration) CompareAndSwap(old, val time.Duration) bool {
|
||||||
return atomic.CompareAndSwapInt64((*int64)(d), int64(old), int64(val))
|
return atomic.CompareAndSwapInt64((*int64)(d), int64(old), int64(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load loads the current duration.
|
||||||
func (d *AtomicDuration) Load() time.Duration {
|
func (d *AtomicDuration) Load() time.Duration {
|
||||||
return time.Duration(atomic.LoadInt64((*int64)(d)))
|
return time.Duration(atomic.LoadInt64((*int64)(d)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets the value to val.
|
||||||
func (d *AtomicDuration) Set(val time.Duration) {
|
func (d *AtomicDuration) Set(val time.Duration) {
|
||||||
atomic.StoreInt64((*int64)(d), int64(val))
|
atomic.StoreInt64((*int64)(d), int64(val))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,22 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// An AtomicFloat64 is an implementation of atomic float64.
|
||||||
type AtomicFloat64 uint64
|
type AtomicFloat64 uint64
|
||||||
|
|
||||||
|
// NewAtomicFloat64 returns an AtomicFloat64.
|
||||||
func NewAtomicFloat64() *AtomicFloat64 {
|
func NewAtomicFloat64() *AtomicFloat64 {
|
||||||
return new(AtomicFloat64)
|
return new(AtomicFloat64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForAtomicFloat64 returns an AtomicFloat64 with given val.
|
||||||
func ForAtomicFloat64(val float64) *AtomicFloat64 {
|
func ForAtomicFloat64(val float64) *AtomicFloat64 {
|
||||||
f := NewAtomicFloat64()
|
f := NewAtomicFloat64()
|
||||||
f.Set(val)
|
f.Set(val)
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add adds val to current value.
|
||||||
func (f *AtomicFloat64) Add(val float64) float64 {
|
func (f *AtomicFloat64) Add(val float64) float64 {
|
||||||
for {
|
for {
|
||||||
old := f.Load()
|
old := f.Load()
|
||||||
@@ -27,14 +31,17 @@ func (f *AtomicFloat64) Add(val float64) float64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompareAndSwap compares current value with old, if equals, set the value to val.
|
||||||
func (f *AtomicFloat64) CompareAndSwap(old, val float64) bool {
|
func (f *AtomicFloat64) CompareAndSwap(old, val float64) bool {
|
||||||
return atomic.CompareAndSwapUint64((*uint64)(f), math.Float64bits(old), math.Float64bits(val))
|
return atomic.CompareAndSwapUint64((*uint64)(f), math.Float64bits(old), math.Float64bits(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load loads the current value.
|
||||||
func (f *AtomicFloat64) Load() float64 {
|
func (f *AtomicFloat64) Load() float64 {
|
||||||
return math.Float64frombits(atomic.LoadUint64((*uint64)(f)))
|
return math.Float64frombits(atomic.LoadUint64((*uint64)(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets the current value to val.
|
||||||
func (f *AtomicFloat64) Set(val float64) {
|
func (f *AtomicFloat64) Set(val float64) {
|
||||||
atomic.StoreUint64((*uint64)(f), math.Float64bits(val))
|
atomic.StoreUint64((*uint64)(f), math.Float64bits(val))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package syncx
|
|||||||
|
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
|
// A Barrier is used to facility the barrier on a resource.
|
||||||
type Barrier struct {
|
type Barrier struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guard guards the given fn on the resource.
|
||||||
func (b *Barrier) Guard(fn func()) {
|
func (b *Barrier) Guard(fn func()) {
|
||||||
b.lock.Lock()
|
b.lock.Lock()
|
||||||
defer b.lock.Unlock()
|
defer b.lock.Unlock()
|
||||||
|
|||||||
@@ -7,17 +7,19 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/core/timex"
|
"github.com/tal-tech/go-zero/core/timex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A Cond is used to wait for conditions.
|
||||||
type Cond struct {
|
type Cond struct {
|
||||||
signal chan lang.PlaceholderType
|
signal chan lang.PlaceholderType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCond returns a Cond.
|
||||||
func NewCond() *Cond {
|
func NewCond() *Cond {
|
||||||
return &Cond{
|
return &Cond{
|
||||||
signal: make(chan lang.PlaceholderType),
|
signal: make(chan lang.PlaceholderType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitWithTimeout wait for signal return remain wait time or timed out
|
// WaitWithTimeout wait for signal return remain wait time or timed out.
|
||||||
func (cond *Cond) WaitWithTimeout(timeout time.Duration) (time.Duration, bool) {
|
func (cond *Cond) WaitWithTimeout(timeout time.Duration) (time.Duration, bool) {
|
||||||
timer := time.NewTimer(timeout)
|
timer := time.NewTimer(timeout)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
@@ -33,7 +35,7 @@ func (cond *Cond) WaitWithTimeout(timeout time.Duration) (time.Duration, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for signal
|
// Wait waits for signals.
|
||||||
func (cond *Cond) Wait() {
|
func (cond *Cond) Wait() {
|
||||||
<-cond.signal
|
<-cond.signal
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,23 +6,27 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/core/lang"
|
"github.com/tal-tech/go-zero/core/lang"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A DoneChan is used as a channel that can be closed multiple times and wait for done.
|
||||||
type DoneChan struct {
|
type DoneChan struct {
|
||||||
done chan lang.PlaceholderType
|
done chan lang.PlaceholderType
|
||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDoneChan returns a DoneChan.
|
||||||
func NewDoneChan() *DoneChan {
|
func NewDoneChan() *DoneChan {
|
||||||
return &DoneChan{
|
return &DoneChan{
|
||||||
done: make(chan lang.PlaceholderType),
|
done: make(chan lang.PlaceholderType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes dc, it's safe to close more than once.
|
||||||
func (dc *DoneChan) Close() {
|
func (dc *DoneChan) Close() {
|
||||||
dc.once.Do(func() {
|
dc.once.Do(func() {
|
||||||
close(dc.done)
|
close(dc.done)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Done returns a channel that can be notified on dc closed.
|
||||||
func (dc *DoneChan) Done() chan lang.PlaceholderType {
|
func (dc *DoneChan) Done() chan lang.PlaceholderType {
|
||||||
return dc.done
|
return dc.done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ import (
|
|||||||
const defaultRefreshInterval = time.Second
|
const defaultRefreshInterval = time.Second
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// ImmutableResourceOption defines the method to customize an ImmutableResource.
|
||||||
ImmutableResourceOption func(resource *ImmutableResource)
|
ImmutableResourceOption func(resource *ImmutableResource)
|
||||||
|
|
||||||
|
// An ImmutableResource is used to manage an immutable resource.
|
||||||
ImmutableResource struct {
|
ImmutableResource struct {
|
||||||
fetch func() (interface{}, error)
|
fetch func() (interface{}, error)
|
||||||
resource interface{}
|
resource interface{}
|
||||||
@@ -22,6 +24,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewImmutableResource returns an ImmutableResource.
|
||||||
func NewImmutableResource(fn func() (interface{}, error), opts ...ImmutableResourceOption) *ImmutableResource {
|
func NewImmutableResource(fn func() (interface{}, error), opts ...ImmutableResourceOption) *ImmutableResource {
|
||||||
// cannot use executors.LessExecutor because of cycle imports
|
// cannot use executors.LessExecutor because of cycle imports
|
||||||
ir := ImmutableResource{
|
ir := ImmutableResource{
|
||||||
@@ -35,6 +38,7 @@ func NewImmutableResource(fn func() (interface{}, error), opts ...ImmutableResou
|
|||||||
return &ir
|
return &ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get gets the immutable resource, fetches automatically if not loaded.
|
||||||
func (ir *ImmutableResource) Get() (interface{}, error) {
|
func (ir *ImmutableResource) Get() (interface{}, error) {
|
||||||
ir.lock.RLock()
|
ir.lock.RLock()
|
||||||
resource := ir.resource
|
resource := ir.resource
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewLockedCalls returns a LockedCalls.
|
||||||
func NewLockedCalls() LockedCalls {
|
func NewLockedCalls() LockedCalls {
|
||||||
return &lockedGroup{
|
return &lockedGroup{
|
||||||
m: make(map[string]*sync.WaitGroup),
|
m: make(map[string]*sync.WaitGroup),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package syncx
|
|||||||
|
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
|
// A ManagedResource is used to manage a resource that might be broken and refetched, like a connection.
|
||||||
type ManagedResource struct {
|
type ManagedResource struct {
|
||||||
resource interface{}
|
resource interface{}
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
@@ -9,6 +10,7 @@ type ManagedResource struct {
|
|||||||
equals func(a, b interface{}) bool
|
equals func(a, b interface{}) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewManagedResource returns a ManagedResource.
|
||||||
func NewManagedResource(generate func() interface{}, equals func(a, b interface{}) bool) *ManagedResource {
|
func NewManagedResource(generate func() interface{}, equals func(a, b interface{}) bool) *ManagedResource {
|
||||||
return &ManagedResource{
|
return &ManagedResource{
|
||||||
generate: generate,
|
generate: generate,
|
||||||
@@ -16,6 +18,7 @@ func NewManagedResource(generate func() interface{}, equals func(a, b interface{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarkBroken marks the resouce broken.
|
||||||
func (mr *ManagedResource) MarkBroken(resource interface{}) {
|
func (mr *ManagedResource) MarkBroken(resource interface{}) {
|
||||||
mr.lock.Lock()
|
mr.lock.Lock()
|
||||||
defer mr.lock.Unlock()
|
defer mr.lock.Unlock()
|
||||||
@@ -25,6 +28,7 @@ func (mr *ManagedResource) MarkBroken(resource interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take takes the resource, if not loaded, generates it.
|
||||||
func (mr *ManagedResource) Take() interface{} {
|
func (mr *ManagedResource) Take() interface{} {
|
||||||
mr.lock.RLock()
|
mr.lock.RLock()
|
||||||
resource := mr.resource
|
resource := mr.resource
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package syncx
|
|||||||
|
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
|
// Once returns a func that guanartees fn can only called once.
|
||||||
func Once(fn func()) func() {
|
func Once(fn func()) func() {
|
||||||
once := new(sync.Once)
|
once := new(sync.Once)
|
||||||
return func() {
|
return func() {
|
||||||
|
|||||||
@@ -2,14 +2,17 @@ package syncx
|
|||||||
|
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
|
|
||||||
|
// A OnceGuard is used to make sure a resouce can be taken once.
|
||||||
type OnceGuard struct {
|
type OnceGuard struct {
|
||||||
done uint32
|
done uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Taken checks if the resource is taken.
|
||||||
func (og *OnceGuard) Taken() bool {
|
func (og *OnceGuard) Taken() bool {
|
||||||
return atomic.LoadUint32(&og.done) == 1
|
return atomic.LoadUint32(&og.done) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take takes the resource, returns true on success, false for otherwise.
|
||||||
func (og *OnceGuard) Take() bool {
|
func (og *OnceGuard) Take() bool {
|
||||||
return atomic.CompareAndSwapUint32(&og.done, 0, 1)
|
return atomic.CompareAndSwapUint32(&og.done, 0, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// PoolOption defines the method to customize a Pool.
|
||||||
PoolOption func(*Pool)
|
PoolOption func(*Pool)
|
||||||
|
|
||||||
node struct {
|
node struct {
|
||||||
@@ -16,6 +17,11 @@ type (
|
|||||||
lastUsed time.Duration
|
lastUsed time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Pool is used to pool resources.
|
||||||
|
// The difference between sync.Pool is that:
|
||||||
|
// 1. the limit of the resouces
|
||||||
|
// 2. max age of the resources can be set
|
||||||
|
// 3. the method to destroy resources can be customized
|
||||||
Pool struct {
|
Pool struct {
|
||||||
limit int
|
limit int
|
||||||
created int
|
created int
|
||||||
@@ -28,6 +34,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewPool returns a Pool.
|
||||||
func NewPool(n int, create func() interface{}, destroy func(interface{}), opts ...PoolOption) *Pool {
|
func NewPool(n int, create func() interface{}, destroy func(interface{}), opts ...PoolOption) *Pool {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("pool size can't be negative or zero")
|
panic("pool size can't be negative or zero")
|
||||||
@@ -49,6 +56,7 @@ func NewPool(n int, create func() interface{}, destroy func(interface{}), opts .
|
|||||||
return pool
|
return pool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get gets a resouce.
|
||||||
func (p *Pool) Get() interface{} {
|
func (p *Pool) Get() interface{} {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
@@ -75,6 +83,7 @@ func (p *Pool) Get() interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put puts a resource back.
|
||||||
func (p *Pool) Put(x interface{}) {
|
func (p *Pool) Put(x interface{}) {
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return
|
return
|
||||||
@@ -91,6 +100,7 @@ func (p *Pool) Put(x interface{}) {
|
|||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithMaxAge returns a function to customize a Pool with given max age.
|
||||||
func WithMaxAge(duration time.Duration) PoolOption {
|
func WithMaxAge(duration time.Duration) PoolOption {
|
||||||
return func(pool *Pool) {
|
return func(pool *Pool) {
|
||||||
pool.maxAge = duration
|
pool.maxAge = duration
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrUseOfCleaned is an error that indicates using a cleaned resource.
|
||||||
var ErrUseOfCleaned = errors.New("using a cleaned resource")
|
var ErrUseOfCleaned = errors.New("using a cleaned resource")
|
||||||
|
|
||||||
|
// A RefResource is used to reference counting a resouce.
|
||||||
type RefResource struct {
|
type RefResource struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
ref int32
|
ref int32
|
||||||
@@ -14,12 +16,14 @@ type RefResource struct {
|
|||||||
clean func()
|
clean func()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRefResource returns a RefResource.
|
||||||
func NewRefResource(clean func()) *RefResource {
|
func NewRefResource(clean func()) *RefResource {
|
||||||
return &RefResource{
|
return &RefResource{
|
||||||
clean: clean,
|
clean: clean,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use uses the resource with reference count incremented.
|
||||||
func (r *RefResource) Use() error {
|
func (r *RefResource) Use() error {
|
||||||
r.lock.Lock()
|
r.lock.Lock()
|
||||||
defer r.lock.Unlock()
|
defer r.lock.Unlock()
|
||||||
@@ -32,6 +36,7 @@ func (r *RefResource) Use() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean cleans a resource with reference count decremented.
|
||||||
func (r *RefResource) Clean() {
|
func (r *RefResource) Clean() {
|
||||||
r.lock.Lock()
|
r.lock.Lock()
|
||||||
defer r.lock.Unlock()
|
defer r.lock.Unlock()
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/core/errorx"
|
"github.com/tal-tech/go-zero/core/errorx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A ResourceManager is a manager that used to manage resources.
|
||||||
type ResourceManager struct {
|
type ResourceManager struct {
|
||||||
resources map[string]io.Closer
|
resources map[string]io.Closer
|
||||||
sharedCalls SharedCalls
|
sharedCalls SharedCalls
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewResourceManager returns a ResourceManager.
|
||||||
func NewResourceManager() *ResourceManager {
|
func NewResourceManager() *ResourceManager {
|
||||||
return &ResourceManager{
|
return &ResourceManager{
|
||||||
resources: make(map[string]io.Closer),
|
resources: make(map[string]io.Closer),
|
||||||
@@ -20,6 +22,7 @@ func NewResourceManager() *ResourceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes the manager.
|
||||||
func (manager *ResourceManager) Close() error {
|
func (manager *ResourceManager) Close() error {
|
||||||
manager.lock.Lock()
|
manager.lock.Lock()
|
||||||
defer manager.lock.Unlock()
|
defer manager.lock.Unlock()
|
||||||
@@ -34,6 +37,7 @@ func (manager *ResourceManager) Close() error {
|
|||||||
return be.Err()
|
return be.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetResource returns the resource associated with given key.
|
||||||
func (manager *ResourceManager) GetResource(key string, create func() (io.Closer, error)) (io.Closer, error) {
|
func (manager *ResourceManager) GetResource(key string, create func() (io.Closer, error)) (io.Closer, error) {
|
||||||
val, err := manager.sharedCalls.Do(key, func() (interface{}, error) {
|
val, err := manager.sharedCalls.Do(key, func() (interface{}, error) {
|
||||||
manager.lock.RLock()
|
manager.lock.RLock()
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewSharedCalls returns a SharedCalls.
|
||||||
func NewSharedCalls() SharedCalls {
|
func NewSharedCalls() SharedCalls {
|
||||||
return &sharedGroup{
|
return &sharedGroup{
|
||||||
calls: make(map[string]*call),
|
calls: make(map[string]*call),
|
||||||
|
|||||||
@@ -5,20 +5,24 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A SpinLock is used as a lock a fast execution.
|
||||||
type SpinLock struct {
|
type SpinLock struct {
|
||||||
lock uint32
|
lock uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lock locks the SpinLock.
|
||||||
func (sl *SpinLock) Lock() {
|
func (sl *SpinLock) Lock() {
|
||||||
for !sl.TryLock() {
|
for !sl.TryLock() {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryLock tries to lock the SpinLock.
|
||||||
func (sl *SpinLock) TryLock() bool {
|
func (sl *SpinLock) TryLock() bool {
|
||||||
return atomic.CompareAndSwapUint32(&sl.lock, 0, 1)
|
return atomic.CompareAndSwapUint32(&sl.lock, 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlock unlocks the SpinLock.
|
||||||
func (sl *SpinLock) Unlock() {
|
func (sl *SpinLock) Unlock() {
|
||||||
atomic.StoreUint32(&sl.lock, 0)
|
atomic.StoreUint32(&sl.lock, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,16 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrTimeout is an error that indicates the borrow timeout.
|
||||||
var ErrTimeout = errors.New("borrow timeout")
|
var ErrTimeout = errors.New("borrow timeout")
|
||||||
|
|
||||||
|
// A TimeoutLimit is used to borrow with timeouts.
|
||||||
type TimeoutLimit struct {
|
type TimeoutLimit struct {
|
||||||
limit Limit
|
limit Limit
|
||||||
cond *Cond
|
cond *Cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTimeoutLimit returns a TimeoutLimit.
|
||||||
func NewTimeoutLimit(n int) TimeoutLimit {
|
func NewTimeoutLimit(n int) TimeoutLimit {
|
||||||
return TimeoutLimit{
|
return TimeoutLimit{
|
||||||
limit: NewLimit(n),
|
limit: NewLimit(n),
|
||||||
@@ -19,6 +22,7 @@ func NewTimeoutLimit(n int) TimeoutLimit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Borrow borrows with given timeout.
|
||||||
func (l TimeoutLimit) Borrow(timeout time.Duration) error {
|
func (l TimeoutLimit) Borrow(timeout time.Duration) error {
|
||||||
if l.TryBorrow() {
|
if l.TryBorrow() {
|
||||||
return nil
|
return nil
|
||||||
@@ -37,6 +41,7 @@ func (l TimeoutLimit) Borrow(timeout time.Duration) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return returns a borrow.
|
||||||
func (l TimeoutLimit) Return() error {
|
func (l TimeoutLimit) Return() error {
|
||||||
if err := l.limit.Return(); err != nil {
|
if err := l.limit.Return(); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -46,6 +51,7 @@ func (l TimeoutLimit) Return() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryBorrow tries a borrow.
|
||||||
func (l TimeoutLimit) TryBorrow() bool {
|
func (l TimeoutLimit) TryBorrow() bool {
|
||||||
return l.limit.TryBorrow()
|
return l.limit.TryBorrow()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user