aboutsummaryrefslogtreecommitdiffstats
path: root/event/event.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2014-10-17 00:08:48 +0800
committerFelix Lange <fjl@twurst.com>2014-10-17 00:50:48 +0800
commit10bbf265b2e8f1906602d2604f755241b8eb49e6 (patch)
tree92626a5824e8a740ed657d5704edbe9dca9cffa3 /event/event.go
parentdac4a8f113b35c67349115115af17c7f1874d939 (diff)
downloadgo-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.go23
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()
}