From f393b600d43bef1f2ac5becc9850c8ed5ee45bf8 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 10 Jan 2014 11:46:18 +0200 Subject: [PATCH] better locking for account guard --- engine/accountlock.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/engine/accountlock.go b/engine/accountlock.go index a781447ed..6ea5c104d 100644 --- a/engine/accountlock.go +++ b/engine/accountlock.go @@ -30,7 +30,7 @@ func init() { type AccountLock struct { queue map[string]chan bool - sync.Mutex + sync.RWMutex } func NewAccountLock() *AccountLock { @@ -38,13 +38,15 @@ func NewAccountLock() *AccountLock { } func (cm *AccountLock) GuardGetCost(name string, handler func() (*CallCost, error)) (reply *CallCost, err error) { - cm.Lock() + cm.RLock() lock, exists := AccLock.queue[name] + cm.RUnlock() if !exists { + cm.Lock() lock = make(chan bool, 1) AccLock.queue[name] = lock + cm.Unlock() } - cm.Unlock() lock <- true reply, err = handler() <-lock @@ -52,13 +54,35 @@ func (cm *AccountLock) GuardGetCost(name string, handler func() (*CallCost, erro } func (cm *AccountLock) Guard(name string, handler func() (float64, error)) (reply float64, err error) { + cm.RLock() lock, exists := AccLock.queue[name] + cm.RUnlock() if !exists { + cm.Lock() lock = make(chan bool, 1) AccLock.queue[name] = lock + cm.Unlock() } lock <- true reply, err = handler() <-lock return } + +func (cm *AccountLock) GuardMany(names []string, handler func() (float64, error)) (reply float64, err error) { + for _, name := range names { + cm.RLock() + lock, exists := AccLock.queue[name] + cm.RUnlock() + if !exists { + cm.Lock() + lock = make(chan bool, 1) + AccLock.queue[name] = lock + cm.Unlock() + } + lock <- true + reply, err = handler() + <-lock + } + return +}