From e73db1d7d226408976ed89d514588a5fee7e87fa Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Fri, 27 Sep 2019 20:51:46 +0800 Subject: [PATCH] Replace mutex with spin-lock --- pool.go | 6 ++++-- pool_func.go | 6 ++++-- spinlock.go | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 spinlock.go diff --git a/pool.go b/pool.go index 75741de1..9af46dec 100644 --- a/pool.go +++ b/pool.go @@ -46,7 +46,7 @@ type Pool struct { release int32 // lock for synchronous operation. - lock sync.Mutex + lock sync.Locker // cond for waiting to get a idle worker. cond *sync.Cond @@ -146,6 +146,7 @@ func NewPool(size int, options ...Option) (*Pool, error) { nonblocking: opts.Nonblocking, maxBlockingTasks: int32(opts.MaxBlockingTasks), panicHandler: opts.PanicHandler, + lock: SpinLock(), } } else { p = &Pool{ @@ -154,9 +155,10 @@ func NewPool(size int, options ...Option) (*Pool, error) { nonblocking: opts.Nonblocking, maxBlockingTasks: int32(opts.MaxBlockingTasks), panicHandler: opts.PanicHandler, + lock: SpinLock(), } } - p.cond = sync.NewCond(&p.lock) + p.cond = sync.NewCond(p.lock) // Start a goroutine to clean up expired workers periodically. go p.periodicallyPurge() diff --git a/pool_func.go b/pool_func.go index 8ffe3add..59d3187d 100644 --- a/pool_func.go +++ b/pool_func.go @@ -46,7 +46,7 @@ type PoolWithFunc struct { release int32 // lock for synchronous operation. - lock sync.Mutex + lock sync.Locker // cond for waiting to get a idle worker. cond *sync.Cond @@ -154,6 +154,7 @@ func NewPoolWithFunc(size int, pf func(interface{}), options ...Option) (*PoolWi nonblocking: opts.Nonblocking, maxBlockingTasks: int32(opts.MaxBlockingTasks), panicHandler: opts.PanicHandler, + lock: SpinLock(), } } else { p = &PoolWithFunc{ @@ -163,9 +164,10 @@ func NewPoolWithFunc(size int, pf func(interface{}), options ...Option) (*PoolWi nonblocking: opts.Nonblocking, maxBlockingTasks: int32(opts.MaxBlockingTasks), panicHandler: opts.PanicHandler, + lock: SpinLock(), } } - p.cond = sync.NewCond(&p.lock) + p.cond = sync.NewCond(p.lock) // Start a goroutine to clean up expired workers periodically. go p.periodicallyPurge() diff --git a/spinlock.go b/spinlock.go new file mode 100644 index 00000000..3b87c875 --- /dev/null +++ b/spinlock.go @@ -0,0 +1,27 @@ +// Copyright 2019 Andy Pan. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package ants + +import ( + "runtime" + "sync" + "sync/atomic" +) + +type spinLock uint32 + +func (sl *spinLock) Lock() { + for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) { + runtime.Gosched() + } +} + +func (sl *spinLock) Unlock() { + atomic.StoreUint32((*uint32)(sl), 0) +} + +func SpinLock() sync.Locker { + return new(spinLock) +}