aboutsummaryrefslogtreecommitdiff
path: root/go/util/concurrent_read_map.go
blob: 41cce8b82e63d620646ba42217fecd53d6e9aa96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package util

import (
	"sync"
)

// A mostly for read map, which can thread-safely
// initialize the map entries.
type ConcurrentReadMap struct {
	rmutex sync.RWMutex
	mutex  sync.Mutex
	Items  map[string]interface{}
}

func NewConcurrentReadMap() *ConcurrentReadMap {
	return &ConcurrentReadMap{Items: make(map[string]interface{})}
}

func (m *ConcurrentReadMap) initMapEntry(key string, newEntry func() interface{}) (value interface{}) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if value, ok := m.Items[key]; ok {
		return value
	}
	value = newEntry()
	m.Items[key] = value
	return value
}

func (m *ConcurrentReadMap) Get(key string, newEntry func() interface{}) interface{} {
	m.rmutex.RLock()
	if value, ok := m.Items[key]; ok {
		m.rmutex.RUnlock()
		return value
	}
	m.rmutex.RUnlock()
	return m.initMapEntry(key, newEntry)
}