func (m *Map) ParallelRange(f func(key, value interface{})) {
	splits := m.splits
	parallel.Range(0, len(splits), 0, func(low, high int) {
		for i := low; i < high; i++ {
			splits[i].parallelRange(f)
		}
	})
}
ParallelRange calls f in parallel for each key and value present in the map.

While iterating through a split of m, ParallelRange holds the corresponding
lock.

ParallelRange does not necessarily correspond to any consistent snapshot of
the Map's contents: no key will be visited more than once, but if the value
for any key is stored or deleted concurrently, ParallelRange may reflect any
mapping for that key from any point during the Range call.
package sync
import (
	"runtime"
	"sync"
	"github.com/exascience/pargo/internal"
	"github.com/exascience/pargo/parallel"
	"github.com/exascience/pargo/speculative"
)
type Hasher interface {
	Hash() uint64
}
type Split struct {
	sync.RWMutex
	Map map[interface{}]interface{}
}
type Map struct {
	splits []Split
}
func NewMap(size int) *Map {
	if size <= 0 {
		size = runtime.GOMAXPROCS(0)
	}
	splits := make([]Split, size)
	for i := range splits {
		splits[i].Map = make(map[interface{}]interface{})
	}
	return &Map{splits}
}
func (m *Map) Split(key Hasher) *Split {
	splits := m.splits
	return &splits[key.Hash()%uint64(len(splits))]
}
func (m *Map) Delete(key Hasher) {
	split := m.Split(key)
	split.Lock()
	delete(split.Map, key)
	split.Unlock()
}
func (m *Map) Load(key Hasher) (value interface{}, ok bool) {
	split := m.Split(key)
	split.RLock()
	value, ok = split.Map[key]
	split.RUnlock()
	return
}
func (m *Map) LoadOrStore(key Hasher, value interface{}) (actual interface{}, loaded bool) {
	split := m.Split(key)
	split.RLock()
	actual, loaded = split.Map[key]
	split.RUnlock()
	if loaded {
		return
	}
	split.Lock()
	if actual, loaded = split.Map[key]; !loaded {
		actual = value
		split.Map[key] = value
	}
	split.Unlock()
	return
}
func (m *Map) LoadOrCompute(key Hasher, computer func() interface{}) (actual interface{}, loaded bool) {
	split := m.Split(key)
	split.RLock()
	actual, loaded = split.Map[key]
	split.RUnlock()
	if loaded {
		return
	}
	value := computer()
	split.Lock()
	if actual, loaded = split.Map[key]; !loaded {
		actual = value
		split.Map[key] = actual
	}
	split.Unlock()
	return
}
func (m *Map) DeleteOrStore(key Hasher, value interface{}) (actual interface{}, deleted bool) {
	split := m.Split(key)
	split.Lock()
	if actual, deleted = split.Map[key]; deleted {
		delete(split.Map, key)
	} else {
		actual = value
		split.Map[key] = value
	}
	split.Unlock()
	return
}
func (m *Map) DeleteOrCompute(key Hasher, computer func() interface{}) (actual interface{}, deleted bool) {
	split := m.Split(key)
	split.Lock()
	if actual, deleted = split.Map[key]; deleted {
		delete(split.Map, key)
	} else {
		actual = computer()
		split.Map[key] = actual
	}
	split.Unlock()
	return
}
func (m *Map) Modify(
	key Hasher,
	modifier func(value interface{}, ok bool) (replacement interface{}, storeNotDelete bool),
) (replacement interface{}, storeNotDelete bool) {
	split := m.Split(key)
	split.Lock()
	value, ok := split.Map[key]
	if replacement, storeNotDelete = modifier(value, ok); storeNotDelete {
		split.Map[key] = replacement
	} else {
		delete(split.Map, key)
	}
	split.Unlock()
	return
}
func (split *Split) srange(f func(key, value interface{}) bool) bool {
	split.Lock()
	defer split.Unlock()
	for key, value := range split.Map {
		if !f(key, value) {
			return false
		}
	}
	return true
}
func (m *Map) Range(f func(key, value interface{}) bool) {
	splits := m.splits
	for i := 0; i < len(splits); i++ {
		if !splits[i].srange(f) {
			return
		}
	}
}
func (split *Split) parallelRange(f func(key, value interface{})) {
	split.Lock()
	defer split.Unlock()
	for key, value := range split.Map {
		f(key, value)
	}
}