@@ -10,8 +10,12 @@ import (
1010 "sync/atomic"
1111)
1212
13- // IgnoreValue can be returned from the func called to NewFromJSON to ignore setting the value
14- var IgnoreValue = & struct { bool }{true }
13+ var (
14+ // IgnoreValue can be returned from the func called to NewFromJSON to ignore setting the value
15+ IgnoreValue = & struct { bool }{true }
16+ // DeleteValue can be returns from Update to delete the value
17+ DeleteValue = & struct { bool }{true }
18+ )
1519
1620// DefaultShardCount is the default number of shards to use when New() or NewFromJSON() are called.
1721const DefaultShardCount = 1 << 4 // 16
@@ -20,94 +24,7 @@ const DefaultShardCount = 1 << 4 // 16
2024type ForEachFunc func (key string , val interface {}) (BreakEarly bool )
2125
2226type CompareAndSwapFunc func (a , b interface {}) bool
23-
24- type lockedMap struct {
25- m map [string ]interface {}
26- l sync.RWMutex
27- }
28-
29- func (ms * lockedMap ) Set (key string , v interface {}) {
30- ms .l .Lock ()
31- ms .m [key ] = v
32- ms .l .Unlock ()
33- }
34-
35- func (ms * lockedMap ) Swap (key string , v interface {}) interface {} {
36- ms .l .Lock ()
37- ov := ms .m [key ]
38- ms .m [key ] = v
39- ms .l .Unlock ()
40- return ov
41- }
42-
43- func (ms * lockedMap ) CompareAndSwap (key string , v interface {}, casFn CompareAndSwapFunc ) bool {
44- ms .l .Lock ()
45- ov := ms .m [key ]
46- ok := casFn (v , ov )
47- if ok {
48- ms .m [key ] = v
49- }
50- ms .l .Unlock ()
51- return ok
52- }
53-
54- func (ms * lockedMap ) Get (key string ) interface {} {
55- ms .l .RLock ()
56- v := ms .m [key ]
57- ms .l .RUnlock ()
58- return v
59- }
60-
61- func (ms * lockedMap ) Has (key string ) bool {
62- ms .l .RLock ()
63- _ , ok := ms .m [key ]
64- ms .l .RUnlock ()
65- return ok
66- }
67-
68- func (ms * lockedMap ) Delete (key string ) {
69- ms .l .Lock ()
70- delete (ms .m , key )
71- ms .l .Unlock ()
72- }
73-
74- func (ms * lockedMap ) DeleteAndGet (key string ) interface {} {
75- ms .l .Lock ()
76- v := ms .m [key ]
77- delete (ms .m , key )
78- ms .l .Unlock ()
79- return v
80- }
81-
82- func (ms * lockedMap ) Len () int {
83- ms .l .RLock ()
84- ln := len (ms .m )
85- ms .l .RUnlock ()
86- return ln
87- }
88-
89- func (ms * lockedMap ) ForEach (fn ForEachFunc ) {
90- ms .l .RLock ()
91- for k , v := range ms .m {
92- if fn (k , v ) {
93- break
94- }
95- }
96- ms .l .RUnlock ()
97- }
98-
99- func (ms * lockedMap ) iter (ch KeyValueChan , wg * sync.WaitGroup ) {
100- var kv KeyValue
101- ms .l .RLock ()
102- for k , v := range ms .m {
103- kv .Key , kv .Value = k , v
104- if ! ch .send (& kv ) {
105- break
106- }
107- }
108- ms .l .RUnlock ()
109- wg .Done ()
110- }
27+ type UpdateFunc func (oldVal interface {}) (newVal interface {})
11128
11229// CMap is a sharded thread-safe concurrent map.
11330type CMap struct {
@@ -188,7 +105,13 @@ func (cm CMap) Has(key string) bool { return cm.shard(key).Has(k
188105func (cm CMap ) Delete (key string ) { cm .shard (key ).Delete (key ) }
189106func (cm CMap ) DeleteAndGet (key string ) interface {} { return cm .shard (key ).DeleteAndGet (key ) }
190107
191- func (cm CMap ) Swap (key string , val interface {}) interface {} { return cm .shard (key ).Swap (key , val ) }
108+ func (cm CMap ) Update (key string , fn func (ov interface {}) interface {}) {
109+ cm .shard (key ).Update (key , fn )
110+ }
111+ func (cm CMap ) Swap (key string , val interface {}) interface {} {
112+ return cm .shard (key ).Swap (key , val )
113+ }
114+
192115func (cm CMap ) CompareAndSwap (key string , val interface {}, eqFn CompareAndSwapFunc ) bool {
193116 return cm .shard (key ).CompareAndSwap (key , val , eqFn )
194117}
@@ -228,12 +151,12 @@ type KeyValue struct {
228151 Value interface {}
229152}
230153
231- // Iter is an alias for IterBuffered(1 )
232- func (cm CMap ) Iter () KeyValueChan { return cm .IterBuffered (1 ) }
154+ // Iter is an alias for IterBuffered(0 )
155+ func (cm CMap ) Iter () KeyValueChan { return cm .IterBuffered (0 ) }
233156
234- // IterBuffered returns a buffered channel sz, to return an unbuffered channel you can pass 1
235- // calling breakLoop will close the channel and consume any remaining values in it .
236- // note that calling breakLoop () will show as a race on the race detector but it's more or less a "safe" race,
157+ // IterBuffered returns a buffered channel sz, to return an unbuffered channel you can pass 0
158+ // ch.Break() on the returned channel can allow breaking early .
159+ // note that calling ch.Break () will show as a race on the race detector but it's more or less a "safe" race,
237160// and it is the only clean way to break out of a channel.
238161func (cm CMap ) IterBuffered (sz int ) KeyValueChan {
239162 ch := make (KeyValueChan , sz )
0 commit comments