Skip to content

Commit 9f7d890

Browse files
committed
move to genx
1 parent 9f69db2 commit 9f7d890

File tree

8 files changed

+81
-311
lines changed

8 files changed

+81
-311
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# cmap [![GoDoc](https://godoc.org/github.com/OneOfOne/cmap?status.svg)](https://godoc.org/github.com/OneOfOne/cmap) [![Build Status](https://travis-ci.org/OneOfOne/cmap.svg?branch=master)](https://travis-ci.org/OneOfOne/cmap) [![Coverage](https://gocover.io/_badge/github.com/OneOfOne/cmap)](https://gocover.io/github.com/OneOfOne/cmap)
2-
--
2+
33

44
CMap (concurrent-map) is a sharded map implementation to support fast concurrent access.
55

cmap.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
// AUTO-GENERATED by cmap-gen
2-
// DO NOT EDIT"
3-
// generated from github.com/OneOfOne/cmap/internal/cmap
1+
// This file was automatically generated by genx.
2+
// Any changes will be lost if this file is regenerated.
3+
// see https://github.com/OneOfOne/genx
4+
// command: genx -pkg ./internal/cmap -t KT=interface{} -t VT=interface{} -m -o ./cmap.go
45

56
package cmap
67

78
import (
89
"context"
910
"sync"
11+
12+
"github.com/OneOfOne/cmap/hashers"
1013
)
1114

15+
// DefaultShardCount is the default number of shards to use when New() or NewFromJSON() are called. The default is 256.
16+
const DefaultShardCount = 1 << 8
17+
1218
// CMap is a concurrent safe sharded map to scale on multiple cores.
1319
type CMap struct {
1420
shards []*LMap
1521
keysPool sync.Pool
16-
// HashFn allows using a custom hash function that's used to determain the key's shard.
17-
// Defaults to DefaultKeyHasher.
22+
// HashFn allows using a custom hash function that's used to determain the key's shard. Defaults to DefaultKeyHasher.
1823
HashFn func(interface{}) uint32
1924
}
2025

@@ -31,17 +36,22 @@ func NewSize(shardCount int) *CMap {
3136
} else if shardCount&(shardCount-1) != 0 {
3237
panic("shardCount must be a power of 2")
3338
}
39+
3440
cm := &CMap{
3541
shards: make([]*LMap, shardCount),
3642
HashFn: DefaultKeyHasher,
3743
}
44+
3845
cm.keysPool.New = func() interface{} {
3946
out := make([]interface{}, 0, DefaultShardCount) // good starting round
40-
return &out // return a ptr to avoid extra allocation on Get/Put
47+
48+
return &out // return a ptr to avoid extra allocation on Get/Put
4149
}
50+
4251
for i := range cm.shards {
4352
cm.shards[i] = NewLMapSize(shardCount)
4453
}
54+
4555
return cm
4656
}
4757

@@ -58,7 +68,7 @@ func (cm *CMap) Set(key interface{}, val interface{}) {
5868
}
5969

6070
// SetIfNotExists will only assign val to key if it wasn't already set.
61-
// Use `CMap.Update` if you need more logic.
71+
// Use `Update` if you need more logic.
6272
func (cm *CMap) SetIfNotExists(key interface{}, val interface{}) (set bool) {
6373
h := cm.HashFn(key)
6474
return cm.shards[h&uint32(len(cm.shards)-1)].SetIfNotExists(key, val)
@@ -122,12 +132,14 @@ func (cm *CMap) Keys() []interface{} {
122132
func (cm *CMap) ForEach(fn func(key interface{}, val interface{}) bool) bool {
123133
keysP := cm.keysPool.Get().(*[]interface{})
124134
defer cm.keysPool.Put(keysP)
135+
125136
for _, lm := range cm.shards {
126137
keys := (*keysP)[:0]
127138
if !lm.ForEach(keys, fn) {
128139
return false
129140
}
130141
}
142+
131143
return false
132144
}
133145

@@ -140,6 +152,7 @@ func (cm *CMap) ForEachLocked(fn func(key interface{}, val interface{}) bool) bo
140152
return false
141153
}
142154
}
155+
143156
return true
144157
}
145158

@@ -192,6 +205,7 @@ func (cm *CMap) iterContext(ctx context.Context, ch chan<- *KV, locked bool) {
192205
return true
193206
}
194207
}
208+
195209
if locked {
196210
_ = cm.ForEachLocked(fn)
197211
} else {
@@ -202,6 +216,9 @@ func (cm *CMap) iterContext(ctx context.Context, ch chan<- *KV, locked bool) {
202216
// NumShards returns the number of shards in the map.
203217
func (cm *CMap) NumShards() int { return len(cm.shards) }
204218

219+
// DefaultKeyHasher is an alias for hashers.TypeHasher32(key).
220+
func DefaultKeyHasher(key interface{}) uint32 { return hashers.TypeHasher32(key) }
221+
205222
// LMap is a simple sync.RWMutex locked map.
206223
// Used by CMap internally for sharding.
207224
type LMap struct {
@@ -214,7 +231,7 @@ func NewLMap() *LMap {
214231
return NewLMapSize(0)
215232
}
216233

217-
// NewLMapSize is the equivalent of `m := make(map[interface{}]interface{}, cap)`
234+
// NewLMapSize is the equivalent of `m := make(map[KT]VT, cap)`
218235
func NewLMapSize(cap int) *LMap {
219236
return &LMap{
220237
m: make(map[interface{}]interface{}, cap),
@@ -306,6 +323,7 @@ func (lm *LMap) ForEach(keys []interface{}, fn func(key interface{}, val interfa
306323
keys = append(keys, key)
307324
}
308325
lm.l.RUnlock()
326+
309327
for _, key := range keys {
310328
lm.l.RLock()
311329
val, ok := lm.m[key]
@@ -317,6 +335,7 @@ func (lm *LMap) ForEach(keys []interface{}, fn func(key interface{}, val interfa
317335
return false
318336
}
319337
}
338+
320339
return true
321340
}
322341

@@ -326,11 +345,13 @@ func (lm *LMap) ForEach(keys []interface{}, fn func(key interface{}, val interfa
326345
func (lm *LMap) ForEachLocked(fn func(key interface{}, val interface{}) bool) bool {
327346
lm.l.RLock()
328347
defer lm.l.RUnlock()
348+
329349
for key, val := range lm.m {
330350
if !fn(key, val) {
331351
return false
332352
}
333353
}
354+
334355
return true
335356
}
336357

cmap_go18_test.go

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import (
44
"context"
55
"fmt"
66
"strconv"
7-
"sync"
87
"testing"
98

109
"github.com/OneOfOne/cmap"
1110
)
1211

13-
var keys [1e5]string
12+
var keys [1e5]interface{}
1413

1514
func init() {
1615
for i := range keys {
@@ -63,26 +62,8 @@ func BenchmarkCMap(b *testing.B) {
6362
}
6463
}
6564

66-
type mutexMap struct {
67-
sync.RWMutex
68-
m map[interface{}]interface{}
69-
}
70-
71-
func (mm *mutexMap) Set(k interface{}, v interface{}) {
72-
mm.Lock()
73-
mm.m[k] = v
74-
mm.Unlock()
75-
}
76-
77-
func (mm *mutexMap) Get(k interface{}) interface{} {
78-
mm.RLock()
79-
v := mm.m[k]
80-
mm.RUnlock()
81-
return v
82-
}
83-
84-
func BenchmarkMutexMap(b *testing.B) {
85-
cm := mutexMap{m: make(map[interface{}]interface{}, cmap.DefaultShardCount)}
65+
func BenchmarkLMap(b *testing.B) {
66+
cm := cmap.NewLMapSize(cmap.DefaultShardCount)
8667
b.ResetTimer()
8768
b.RunParallel(func(pb *testing.PB) {
8869
var i int
@@ -96,6 +77,6 @@ func BenchmarkMutexMap(b *testing.B) {
9677
}
9778
})
9879
if testing.Verbose() {
99-
b.Logf("size: %v", len(cm.m))
80+
b.Logf("size: %v", cm.Len())
10081
}
10182
}

0 commit comments

Comments
 (0)