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  }