diff options
author | Felix Lange <fjl@twurst.com> | 2014-10-17 00:08:48 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2014-10-17 00:50:48 +0800 |
commit | 10bbf265b2e8f1906602d2604f755241b8eb49e6 (patch) | |
tree | 92626a5824e8a740ed657d5704edbe9dca9cffa3 /event/event.go | |
parent | dac4a8f113b35c67349115115af17c7f1874d939 (diff) | |
download | go-tangerine-10bbf265b2e8f1906602d2604f755241b8eb49e6.tar.gz go-tangerine-10bbf265b2e8f1906602d2604f755241b8eb49e6.tar.zst go-tangerine-10bbf265b2e8f1906602d2604f755241b8eb49e6.zip |
event: make Unsubscribe idempotent
Diffstat (limited to 'event/event.go')
-rw-r--r-- | event/event.go | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/event/event.go b/event/event.go index 09759ee50..344d1e3f6 100644 --- a/event/event.go +++ b/event/event.go @@ -124,14 +124,16 @@ func posdelete(slice []*muxsub, pos int) []*muxsub { type muxsub struct { mux *TypeMux - mutex sync.RWMutex + closeMu sync.Mutex closing chan struct{} + closed bool // these two are the same channel. they are stored separately so // postC can be set to nil without affecting the return value of // Chan. - readC <-chan interface{} - postC chan<- interface{} + postMu sync.RWMutex + readC <-chan interface{} + postC chan<- interface{} } func newsub(mux *TypeMux) *muxsub { @@ -154,18 +156,25 @@ func (s *muxsub) Unsubscribe() { } func (s *muxsub) closewait() { + s.closeMu.Lock() + defer s.closeMu.Unlock() + if s.closed { + return + } close(s.closing) - s.mutex.Lock() + s.closed = true + + s.postMu.Lock() close(s.postC) s.postC = nil - s.mutex.Unlock() + s.postMu.Unlock() } func (s *muxsub) deliver(ev interface{}) { - s.mutex.RLock() + s.postMu.RLock() select { case s.postC <- ev: case <-s.closing: } - s.mutex.RUnlock() + s.postMu.RUnlock() } |