switch to "hat" pattern for mutexes

--HG--
branch : adc
This commit is contained in:
mappu 2017-11-22 20:07:26 +13:00
parent dc3051fd38
commit 2fa40642a9
2 changed files with 20 additions and 19 deletions

View File

@ -16,8 +16,9 @@ type HubConnection struct {
// Current remote status // Current remote status
HubName string HubName string
State ConnectionState State ConnectionState
usersMut sync.RWMutex
users map[string]UserInfo users map[string]UserInfo
userLock sync.RWMutex
proto Protocol proto Protocol
@ -33,8 +34,8 @@ type HubConnection struct {
// Thread-safe user accessor. // Thread-safe user accessor.
func (this *HubConnection) Users(cb func(*map[string]UserInfo) error) error { func (this *HubConnection) Users(cb func(*map[string]UserInfo) error) error {
this.userLock.Lock() this.usersMut.Lock()
defer this.userLock.Unlock() defer this.usersMut.Unlock()
return cb(&this.users) return cb(&this.users)
} }
@ -48,16 +49,16 @@ func (this *HubConnection) SayPrivate(recipient string, message string) {
} }
func (this *HubConnection) UserExists(nick string) bool { func (this *HubConnection) UserExists(nick string) bool {
this.userLock.RLock() this.usersMut.RLock()
defer this.userLock.RUnlock() defer this.usersMut.RUnlock()
_, already_existed := this.users[nick] _, already_existed := this.users[nick]
return already_existed return already_existed
} }
func (this *HubConnection) UserCount() int { func (this *HubConnection) UserCount() int {
this.userLock.RLock() this.usersMut.RLock()
defer this.userLock.RUnlock() defer this.usersMut.RUnlock()
return len(this.users) return len(this.users)
} }
@ -65,9 +66,9 @@ func (this *HubConnection) UserCount() int {
func (this *HubConnection) userJoined_NameOnly(nick string) { func (this *HubConnection) userJoined_NameOnly(nick string) {
if !this.UserExists(nick) { if !this.UserExists(nick) {
this.userLock.Lock() this.usersMut.Lock()
this.users[nick] = *NewUserInfo(nick) this.users[nick] = *NewUserInfo(nick)
this.userLock.Unlock() // Don't lock over a processEvent boundary this.usersMut.Unlock() // Don't lock over a processEvent boundary
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick}) this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick})
} }
@ -75,10 +76,10 @@ func (this *HubConnection) userJoined_NameOnly(nick string) {
func (this *HubConnection) userJoined_Full(uinf *UserInfo) { func (this *HubConnection) userJoined_Full(uinf *UserInfo) {
// n.b. also called when we get a replacement MyINFO for someone // n.b. also called when we get a replacement MyINFO for someone
this.userLock.Lock() this.usersMut.Lock()
_, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex _, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex
this.users[uinf.Nick] = *uinf this.users[uinf.Nick] = *uinf
this.userLock.Unlock() // Don't lock over a processEvent boundary this.usersMut.Unlock() // Don't lock over a processEvent boundary
if !userExisted { if !userExisted {
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick}) this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick})

View File

@ -117,9 +117,9 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
} }
case "$Quit": case "$Quit":
this.hc.userLock.Lock() this.hc.usersMut.Lock()
delete(this.hc.users, commandParts[1]) delete(this.hc.users, commandParts[1])
this.hc.userLock.Unlock() // Don't lock over a processEvent boundary this.hc.usersMut.Unlock() // Don't lock over a processEvent boundary
this.hc.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]}) this.hc.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]})
@ -156,8 +156,8 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
// Mark all mentioned nicks as being operators, and all unmentioned nicks // Mark all mentioned nicks as being operators, and all unmentioned nicks
// as being /not/ an operator. (second pass minimises RW mutex use) // as being /not/ an operator. (second pass minimises RW mutex use)
func() { func() {
this.hc.userLock.Lock() this.hc.usersMut.Lock()
defer this.hc.userLock.Unlock() defer this.hc.usersMut.Unlock()
for nick, userinfo := range this.hc.users { for nick, userinfo := range this.hc.users {
_, isop := opmap[nick] _, isop := opmap[nick]
@ -182,7 +182,7 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
} }
case "$UserIP": case "$UserIP":
this.hc.userLock.Lock() this.hc.usersMut.Lock()
pairs := strings.Split(commandParts[1], "$$") pairs := strings.Split(commandParts[1], "$$")
notifyOfUpdate := make([]string, 0, len(pairs)) notifyOfUpdate := make([]string, 0, len(pairs))
@ -211,7 +211,7 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
} }
} }
this.hc.userLock.Unlock() this.hc.usersMut.Unlock()
for _, nick := range notifyOfUpdate { for _, nick := range notifyOfUpdate {
this.hc.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: nick}) this.hc.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: nick})