-
Notifications
You must be signed in to change notification settings - Fork 0
/
ConcurrentPermanentMap.go
136 lines (110 loc) · 2.96 KB
/
ConcurrentPermanentMap.go
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package util
import (
"errors"
"fmt"
"sync"
)
// keys are strings
type ConcurrentPermanentMap struct {
mut sync.Mutex
m map[string]PermanentMapItem
}
type PermanentMapItem struct {
value string
itemValueType MapItemValueType // URL or paste
}
type CPMNonExistentKeyError struct{}
func (e CPMNonExistentKeyError) Error() string {
return "ConcurrentPermanentMap: nonexistent key"
}
func (pmi *PermanentMapItem) MapItemToString() string {
return fmt.Sprintf("PermanentMapItem{value:%#v}", pmi.value)
}
func (pmi *PermanentMapItem) GetValue() string {
return pmi.value
}
func (pmi *PermanentMapItem) GetType() MapItemType {
return MapItemType{
isTemporary: false,
valueType: pmi.itemValueType,
}
}
func (emi *PermanentMapItem) GetExpiryTime() int64 {
return -1
}
func (cpm *ConcurrentPermanentMap) NumItems() int {
cpm.mut.Lock()
defer cpm.mut.Unlock()
return len(cpm.m)
}
// You can call this on nil receiver
func (*ConcurrentPermanentMap) BeginConstruction(stored_map_length int64, expiry_callback ExpiryCallback) ConcurrentMap {
m := make(map[string]PermanentMapItem, stored_map_length)
return &ConcurrentPermanentMap{
mut: sync.Mutex{},
m: m,
}
}
// Caller must check that the key_str is not already in the map.
func (cpm *ConcurrentPermanentMap) ContinueConstruction(key_str string, value_str string, expiry_time int64, item_value_type MapItemValueType) {
// just add it to the map
cpm.m[string(key_str)] = PermanentMapItem{
value: value_str,
itemValueType: item_value_type,
}
}
func (cpm *ConcurrentPermanentMap) FinishConstruction() {} // Does nothing.
// Returns an error if the entry already exists, otherwise returns nil.
func (cpm *ConcurrentPermanentMap) Put_New_Entry(key string, value string, _ int64, item_value_type MapItemValueType) error {
cpm.mut.Lock()
defer cpm.mut.Unlock()
// if entry already exists, return an error
_, ok := cpm.m[key]
if ok {
return errors.New("Entry already exists!!")
}
cpm.m[key] = PermanentMapItem{
value: value,
itemValueType: item_value_type,
}
return nil
}
func (cpm *ConcurrentPermanentMap) Get_Entry(key string) (MapItem, error) {
// 1. acquire read lock
cpm.mut.Lock()
defer cpm.mut.Unlock()
// 2. check if it's in the map
map_item, ok := cpm.m[key]
// If the key doesn't exist
if !ok {
// return error saying key doesn't exist
return nil, CPMNonExistentKeyError{}
}
return &map_item, nil
}
func NewEmptyConcurrentPermanentMap() *ConcurrentPermanentMap {
return &ConcurrentPermanentMap{
mut: sync.Mutex{},
m: make(map[string]PermanentMapItem),
}
}
/*
type CPMItem struct {
Key string
Value string
}
func NewConcurrentPermanentMapFromSlice(kv_pairs []CPMItem) *ConcurrentPermanentMap {
m := make(map[string]string, len(kv_pairs))
for _, cpm_item := range kv_pairs {
m[cpm_item.Key] = cpm_item.Value
}
return &ConcurrentPermanentMap{
mut: sync.Mutex{},
m: m,
}
}
type TTLMap [K any, V any] struct {
Data []T
queue chan[K]
Map map[K]V
}*/