diff options
author | Felix Lange <fjl@twurst.com> | 2014-10-09 01:04:58 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2014-10-09 01:04:58 +0800 |
commit | e83a99903994eaadec3b58822dd18682649ac9dc (patch) | |
tree | 5b882a92766cc3835da0966b86b415792a17e29f | |
parent | a38dafcc57d296447db9748c8c85df6c58b243fb (diff) | |
download | go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar.gz go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar.bz2 go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar.lz go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar.xz go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.tar.zst go-tangerine-e83a99903994eaadec3b58822dd18682649ac9dc.zip |
eth: fix filter map data race
This commit also documents (but doesn't enforce) that filters
are immutable while they're installed. This required a minor API
change.
-rw-r--r-- | ethereum.go | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/ethereum.go b/ethereum.go index b83ceb12f..204f30bec 100644 --- a/ethereum.go +++ b/ethereum.go @@ -95,7 +95,9 @@ type Ethereum struct { isUpToDate bool - filters map[int]*ethchain.Filter + filterMu sync.RWMutex + filterId int + filters map[int]*ethchain.Filter } func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager *ethcrypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error) { @@ -594,22 +596,29 @@ out: } } -var filterId = 0 - -func (self *Ethereum) InstallFilter(object map[string]interface{}) (*ethchain.Filter, int) { - defer func() { filterId++ }() - - filter := ethchain.NewFilterFromMap(object, self) - self.filters[filterId] = filter - - return filter, filterId +// InstallFilter adds filter for blockchain events. +// The filter's callbacks will run for matching blocks and messages. +// The filter should not be modified after it has been installed. +func (self *Ethereum) InstallFilter(filter *ethchain.Filter) (id int) { + self.filterMu.Lock() + id = self.filterId + self.filters[id] = filter + self.filterId++ + self.filterMu.Unlock() + return id } func (self *Ethereum) UninstallFilter(id int) { + self.filterMu.Lock() delete(self.filters, id) + self.filterMu.Unlock() } +// GetFilter retrieves a filter installed using InstallFilter. +// The filter may not be modified. func (self *Ethereum) GetFilter(id int) *ethchain.Filter { + self.filterMu.RLock() + defer self.filterMu.RUnlock() return self.filters[id] } @@ -627,14 +636,17 @@ out: break out case block := <-blockChan: if block, ok := block.Resource.(*ethchain.Block); ok { + self.filterMu.RLock() for _, filter := range self.filters { if filter.BlockCallback != nil { filter.BlockCallback(block) } } + self.filterMu.RUnlock() } case msg := <-messageChan: if messages, ok := msg.Resource.(ethstate.Messages); ok { + self.filterMu.RLock() for _, filter := range self.filters { if filter.MessageCallback != nil { msgs := filter.FilterMessages(messages) @@ -643,6 +655,7 @@ out: } } } + self.filterMu.RUnlock() } } } |