Kevacoin stratum server for solo-mining
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
2.9 KiB

10 years ago
// Generated from https://github.com/streamrail/concurrent-map
package stratum
import (
"hash/fnv"
"sync"
)
var SHARD_COUNT = 32
// TODO: Add Keys function which returns an array of keys for the map.
// A "thread" safe map of type string:*Miner.
// To avoid lock bottlenecks this map is dived to several (SHARD_COUNT) map shards.
type MinersMap []*MinersMapShared
type MinersMapShared struct {
items map[string]*Miner
sync.RWMutex // Read Write mutex, guards access to internal map.
}
// Creates a new concurrent map.
func NewMinersMap() MinersMap {
m := make(MinersMap, SHARD_COUNT)
for i := 0; i < SHARD_COUNT; i++ {
m[i] = &MinersMapShared{items: make(map[string]*Miner)}
}
return m
}
// Returns shard under given key
func (m MinersMap) GetShard(key string) *MinersMapShared {
hasher := fnv.New32()
hasher.Write([]byte(key))
return m[int(hasher.Sum32())%SHARD_COUNT]
}
// Sets the given value under the specified key.
func (m *MinersMap) Set(key string, value *Miner) {
// Get map shard.
shard := m.GetShard(key)
shard.Lock()
defer shard.Unlock()
shard.items[key] = value
}
// Retrieves an element from map under given key.
func (m MinersMap) Get(key string) (*Miner, bool) {
// Get shard
shard := m.GetShard(key)
shard.RLock()
defer shard.RUnlock()
// Get item from shard.
val, ok := shard.items[key]
return val, ok
}
// Returns the number of elements within the map.
func (m MinersMap) Count() int {
count := 0
for i := 0; i < SHARD_COUNT; i++ {
shard := m[i]
shard.RLock()
count += len(shard.items)
shard.RUnlock()
}
return count
}
// Looks up an item under specified key
func (m *MinersMap) Has(key string) bool {
// Get shard
shard := m.GetShard(key)
shard.RLock()
defer shard.RUnlock()
// See if element is within shard.
_, ok := shard.items[key]
return ok
}
// Removes an element from the map.
func (m *MinersMap) Remove(key string) {
// Try to get shard.
shard := m.GetShard(key)
shard.Lock()
defer shard.Unlock()
delete(shard.items, key)
}
// Checks if map is empty.
func (m *MinersMap) IsEmpty() bool {
return m.Count() == 0
}
// Used by the Iter & IterBuffered functions to wrap two variables together over a channel,
type Tuple struct {
Key string
Val *Miner
}
// Returns an iterator which could be used in a for range loop.
func (m MinersMap) Iter() <-chan Tuple {
ch := make(chan Tuple)
go func() {
// Foreach shard.
for _, shard := range m {
// Foreach key, value pair.
shard.RLock()
for key, val := range shard.items {
ch <- Tuple{key, val}
}
shard.RUnlock()
}
close(ch)
}()
return ch
}
// Returns a buffered iterator which could be used in a for range loop.
func (m MinersMap) IterBuffered() <-chan Tuple {
ch := make(chan Tuple, m.Count())
go func() {
// Foreach shard.
for _, shard := range m {
// Foreach key, value pair.
shard.RLock()
for key, val := range shard.items {
ch <- Tuple{key, val}
}
shard.RUnlock()
}
close(ch)
}()
return ch
}