github.com/iainanderson83/datastructures@v0.0.4-0.20191103204413-889e20b53bcf/hashmap/orderedmap.go (about) 1 package hashmap 2 3 import "sync/atomic" 4 5 // OrderedMap is an ordered variant of Hashmap. 6 type OrderedMap struct { 7 lock uintptr 8 i []string 9 m *Hashmap 10 } 11 12 // NewOrderedMap creates a new ordered map with the specified hashing function. 13 func NewOrderedMap(fn func(string) uint64) *OrderedMap { 14 return &OrderedMap{m: NewHashmap(fn)} 15 } 16 17 // Iter calls the specified cb for each key/value pair in the map 18 // in the inserted order. 19 func (o *OrderedMap) Iter(fn func(k string, v interface{}) bool) { 20 for { 21 if atomic.CompareAndSwapUintptr(&o.lock, 0, 1) { 22 break 23 } 24 } 25 26 for i := range o.i { 27 v, b := o.m.Lookup(o.i[i]) 28 if !b { 29 o.i = append(o.i[:i], o.i[i+1:]...) 30 continue 31 } 32 33 if !fn(o.i[i], v) { 34 atomic.StoreUintptr(&o.lock, 0) 35 return 36 } 37 } 38 39 atomic.StoreUintptr(&o.lock, 0) 40 } 41 42 // Lookup returns the value associated with the specified key in the map. 43 func (o *OrderedMap) Lookup(k string) (interface{}, bool) { 44 for { 45 if atomic.CompareAndSwapUintptr(&o.lock, 0, 1) { 46 break 47 } 48 } 49 50 v, b := o.m.Lookup(k) 51 52 atomic.StoreUintptr(&o.lock, 0) 53 return v, b 54 } 55 56 // Delete removes the value associated with the specified key from the map. 57 func (o *OrderedMap) Delete(k string) bool { 58 for { 59 if atomic.CompareAndSwapUintptr(&o.lock, 0, 1) { 60 break 61 } 62 } 63 64 deleted := o.m.Delete(k) 65 if deleted { 66 idx := -1 67 for i := range o.i { 68 if o.i[i] == k { 69 idx = i 70 break 71 } 72 } 73 74 if idx >= 0 { 75 o.i = append(o.i[:idx], o.i[idx+1:]...) 76 } 77 } 78 79 atomic.StoreUintptr(&o.lock, 0) 80 return deleted 81 } 82 83 // Add adds the specified value to the map with the specified key. 84 func (o *OrderedMap) Add(k string, v interface{}) bool { 85 for { 86 if atomic.CompareAndSwapUintptr(&o.lock, 0, 1) { 87 break 88 } 89 } 90 91 added := o.m.Add(k, v) 92 if added { 93 o.i = append(o.i, k) 94 } 95 96 atomic.StoreUintptr(&o.lock, 0) 97 return added 98 } 99 100 // Len returns the number of elements in the map. 101 func (o *OrderedMap) Len() int { 102 for { 103 if atomic.CompareAndSwapUintptr(&o.lock, 0, 1) { 104 break 105 } 106 } 107 108 length := len(o.i) 109 110 atomic.StoreUintptr(&o.lock, 0) 111 return length 112 }