3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-25 21:39:25 +01:00

Merge pull request #160 from slingamn/cache.4

fix a race in regenerateMembersCache
This commit is contained in:
Shivaram Lingamneni 2017-11-08 22:18:25 -05:00 committed by GitHub
commit d5832bf765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -24,6 +24,7 @@ type Channel struct {
key string
members MemberSet
membersCache []*Client // allow iteration over channel members without holding the lock
membersCacheMutex sync.Mutex // tier 2; see `regenerateMembersCache`
name string
nameCasefolded string
server *Server
@ -67,10 +68,15 @@ func NewChannel(s *Server, name string, addDefaultModes bool) *Channel {
}
func (channel *Channel) regenerateMembersCache() {
// this is eventually consistent even without holding the writable Lock()
// this is eventually consistent even without holding stateMutex.Lock()
// throughout the update; all updates to `members` while holding Lock()
// have a serial order, so the call to `regenerateMembersCache` that
// happens-after the last one will see *all* the updates
// happens-after the last one will see *all* the updates. then,
// `membersCacheMutex` ensures that this final read is correctly paired
// with the final write to `membersCache`.
channel.membersCacheMutex.Lock()
defer channel.membersCacheMutex.Unlock()
channel.stateMutex.RLock()
result := make([]*Client, len(channel.members))
i := 0