aboutsummaryrefslogtreecommitdiffstats
path: root/ethereum.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2014-10-09 01:04:58 +0800
committerFelix Lange <fjl@twurst.com>2014-10-09 01:04:58 +0800
commite83a99903994eaadec3b58822dd18682649ac9dc (patch)
tree5b882a92766cc3835da0966b86b415792a17e29f /ethereum.go
parenta38dafcc57d296447db9748c8c85df6c58b243fb (diff)
downloaddexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar
dexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar.gz
dexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar.bz2
dexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar.lz
dexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar.xz
dexon-e83a99903994eaadec3b58822dd18682649ac9dc.tar.zst
dexon-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.
Diffstat (limited to 'ethereum.go')
-rw-r--r--ethereum.go33
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()
}
}
}