github.com/zhongdalu/gf@v1.0.0/g/container/gmap/gmap_link_map.go (about)

     1  // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with gm file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  
     7  package gmap
     8  
     9  import (
    10  	"encoding/json"
    11  
    12  	"github.com/zhongdalu/gf/g/util/gconv"
    13  
    14  	"github.com/zhongdalu/gf/g/container/glist"
    15  	"github.com/zhongdalu/gf/g/container/gvar"
    16  	"github.com/zhongdalu/gf/g/internal/rwmutex"
    17  )
    18  
    19  type ListMap struct {
    20  	mu   *rwmutex.RWMutex
    21  	data map[interface{}]*glist.Element
    22  	list *glist.List
    23  }
    24  
    25  type gListMapNode struct {
    26  	key   interface{}
    27  	value interface{}
    28  }
    29  
    30  // NewListMap returns an empty link map.
    31  // ListMap is backed by a hash table to store values and doubly-linked list to store ordering.
    32  // The parameter <unsafe> used to specify whether using map in un-concurrent-safety,
    33  // which is false in default, means concurrent-safe.
    34  func NewListMap(unsafe ...bool) *ListMap {
    35  	return &ListMap{
    36  		mu:   rwmutex.New(unsafe...),
    37  		data: make(map[interface{}]*glist.Element),
    38  		list: glist.New(true),
    39  	}
    40  }
    41  
    42  // NewListMapFrom returns a link map from given map <data>.
    43  // Note that, the param <data> map will be set as the underlying data map(no deep copy),
    44  // there might be some concurrent-safe issues when changing the map outside.
    45  func NewListMapFrom(data map[interface{}]interface{}, unsafe ...bool) *ListMap {
    46  	m := NewListMap(unsafe...)
    47  	m.Sets(data)
    48  	return m
    49  }
    50  
    51  // Iterator is alias of IteratorAsc.
    52  func (m *ListMap) Iterator(f func(key, value interface{}) bool) {
    53  	m.IteratorAsc(f)
    54  }
    55  
    56  // IteratorAsc iterates the map in ascending order with given callback function <f>.
    57  // If <f> returns true, then it continues iterating; or false to stop.
    58  func (m *ListMap) IteratorAsc(f func(key interface{}, value interface{}) bool) {
    59  	m.mu.RLock()
    60  	defer m.mu.RUnlock()
    61  	node := (*gListMapNode)(nil)
    62  	m.list.IteratorAsc(func(e *glist.Element) bool {
    63  		node = e.Value.(*gListMapNode)
    64  		return f(node.key, node.value)
    65  	})
    66  }
    67  
    68  // IteratorDesc iterates the map in descending order with given callback function <f>.
    69  // If <f> returns true, then it continues iterating; or false to stop.
    70  func (m *ListMap) IteratorDesc(f func(key interface{}, value interface{}) bool) {
    71  	m.mu.RLock()
    72  	defer m.mu.RUnlock()
    73  	node := (*gListMapNode)(nil)
    74  	m.list.IteratorDesc(func(e *glist.Element) bool {
    75  		node = e.Value.(*gListMapNode)
    76  		return f(node.key, node.value)
    77  	})
    78  }
    79  
    80  // Clone returns a new link map with copy of current map data.
    81  func (m *ListMap) Clone(unsafe ...bool) *ListMap {
    82  	return NewListMapFrom(m.Map(), unsafe...)
    83  }
    84  
    85  // Clear deletes all data of the map, it will remake a new underlying data map.
    86  func (m *ListMap) Clear() {
    87  	m.mu.Lock()
    88  	m.data = make(map[interface{}]*glist.Element)
    89  	m.list = glist.New(true)
    90  	m.mu.Unlock()
    91  }
    92  
    93  // Map returns a copy of the data of the map.
    94  func (m *ListMap) Map() map[interface{}]interface{} {
    95  	m.mu.RLock()
    96  	node := (*gListMapNode)(nil)
    97  	data := make(map[interface{}]interface{}, len(m.data))
    98  	m.list.IteratorAsc(func(e *glist.Element) bool {
    99  		node = e.Value.(*gListMapNode)
   100  		data[node.key] = node.value
   101  		return true
   102  	})
   103  	m.mu.RUnlock()
   104  	return data
   105  }
   106  
   107  // Set sets key-value to the map.
   108  func (m *ListMap) Set(key interface{}, value interface{}) {
   109  	m.mu.Lock()
   110  	if e, ok := m.data[key]; !ok {
   111  		m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   112  	} else {
   113  		e.Value = &gListMapNode{key, value}
   114  	}
   115  	m.mu.Unlock()
   116  }
   117  
   118  // Sets batch sets key-values to the map.
   119  func (m *ListMap) Sets(data map[interface{}]interface{}) {
   120  	m.mu.Lock()
   121  	for key, value := range data {
   122  		if e, ok := m.data[key]; !ok {
   123  			m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   124  		} else {
   125  			e.Value = &gListMapNode{key, value}
   126  		}
   127  	}
   128  	m.mu.Unlock()
   129  }
   130  
   131  // Search searches the map with given <key>.
   132  // Second return parameter <found> is true if key was found, otherwise false.
   133  func (m *ListMap) Search(key interface{}) (value interface{}, found bool) {
   134  	m.mu.RLock()
   135  	if e, ok := m.data[key]; ok {
   136  		value = e.Value.(*gListMapNode).value
   137  		found = ok
   138  	}
   139  	m.mu.RUnlock()
   140  	return
   141  }
   142  
   143  // Get returns the value by given <key>.
   144  func (m *ListMap) Get(key interface{}) (value interface{}) {
   145  	m.mu.RLock()
   146  	if e, ok := m.data[key]; ok {
   147  		value = e.Value.(*gListMapNode).value
   148  	}
   149  	m.mu.RUnlock()
   150  	return
   151  }
   152  
   153  // doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
   154  // if not exists, set value to the map with given <key>,
   155  // or else just return the existing value.
   156  //
   157  // When setting value, if <value> is type of <func() interface {}>,
   158  // it will be executed with mutex.Lock of the map,
   159  // and its return value will be set to the map with <key>.
   160  //
   161  // It returns value with given <key>.
   162  func (m *ListMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
   163  	m.mu.Lock()
   164  	defer m.mu.Unlock()
   165  	if e, ok := m.data[key]; ok {
   166  		return e.Value.(*gListMapNode).value
   167  	}
   168  	if f, ok := value.(func() interface{}); ok {
   169  		value = f()
   170  	}
   171  	m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   172  	return value
   173  }
   174  
   175  // GetOrSet returns the value by key,
   176  // or set value with given <value> if not exist and returns this value.
   177  func (m *ListMap) GetOrSet(key interface{}, value interface{}) interface{} {
   178  	if v, ok := m.Search(key); !ok {
   179  		return m.doSetWithLockCheck(key, value)
   180  	} else {
   181  		return v
   182  	}
   183  }
   184  
   185  // GetOrSetFunc returns the value by key,
   186  // or sets value with return value of callback function <f> if not exist
   187  // and returns this value.
   188  func (m *ListMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
   189  	if v, ok := m.Search(key); !ok {
   190  		return m.doSetWithLockCheck(key, f())
   191  	} else {
   192  		return v
   193  	}
   194  }
   195  
   196  // GetOrSetFuncLock returns the value by key,
   197  // or sets value with return value of callback function <f> if not exist
   198  // and returns this value.
   199  //
   200  // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
   201  // with mutex.Lock of the map.
   202  func (m *ListMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
   203  	if v, ok := m.Search(key); !ok {
   204  		return m.doSetWithLockCheck(key, f)
   205  	} else {
   206  		return v
   207  	}
   208  }
   209  
   210  // GetVar returns a gvar.Var with the value by given <key>.
   211  // The returned gvar.Var is un-concurrent safe.
   212  func (m *ListMap) GetVar(key interface{}) *gvar.Var {
   213  	return gvar.New(m.Get(key), true)
   214  }
   215  
   216  // GetVarOrSet returns a gvar.Var with result from GetVarOrSet.
   217  // The returned gvar.Var is un-concurrent safe.
   218  func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var {
   219  	return gvar.New(m.GetOrSet(key, value), true)
   220  }
   221  
   222  // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc.
   223  // The returned gvar.Var is un-concurrent safe.
   224  func (m *ListMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var {
   225  	return gvar.New(m.GetOrSetFunc(key, f), true)
   226  }
   227  
   228  // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock.
   229  // The returned gvar.Var is un-concurrent safe.
   230  func (m *ListMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var {
   231  	return gvar.New(m.GetOrSetFuncLock(key, f), true)
   232  }
   233  
   234  // SetIfNotExist sets <value> to the map if the <key> does not exist, then return true.
   235  // It returns false if <key> exists, and <value> would be ignored.
   236  func (m *ListMap) SetIfNotExist(key interface{}, value interface{}) bool {
   237  	if !m.Contains(key) {
   238  		m.doSetWithLockCheck(key, value)
   239  		return true
   240  	}
   241  	return false
   242  }
   243  
   244  // SetIfNotExistFunc sets value with return value of callback function <f>, then return true.
   245  // It returns false if <key> exists, and <value> would be ignored.
   246  func (m *ListMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
   247  	if !m.Contains(key) {
   248  		m.doSetWithLockCheck(key, f())
   249  		return true
   250  	}
   251  	return false
   252  }
   253  
   254  // SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true.
   255  // It returns false if <key> exists, and <value> would be ignored.
   256  //
   257  // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
   258  // it executes function <f> with mutex.Lock of the map.
   259  func (m *ListMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
   260  	if !m.Contains(key) {
   261  		m.doSetWithLockCheck(key, f)
   262  		return true
   263  	}
   264  	return false
   265  }
   266  
   267  // Remove deletes value from map by given <key>, and return this deleted value.
   268  func (m *ListMap) Remove(key interface{}) (value interface{}) {
   269  	m.mu.Lock()
   270  	if e, ok := m.data[key]; ok {
   271  		value = e.Value.(*gListMapNode).value
   272  		delete(m.data, key)
   273  		m.list.Remove(e)
   274  	}
   275  	m.mu.Unlock()
   276  	return
   277  }
   278  
   279  // Removes batch deletes values of the map by keys.
   280  func (m *ListMap) Removes(keys []interface{}) {
   281  	m.mu.Lock()
   282  	for _, key := range keys {
   283  		if e, ok := m.data[key]; ok {
   284  			delete(m.data, key)
   285  			m.list.Remove(e)
   286  		}
   287  	}
   288  	m.mu.Unlock()
   289  }
   290  
   291  // Keys returns all keys of the map as a slice in ascending order.
   292  func (m *ListMap) Keys() []interface{} {
   293  	m.mu.RLock()
   294  	keys := make([]interface{}, m.list.Len())
   295  	index := 0
   296  	m.list.IteratorAsc(func(e *glist.Element) bool {
   297  		keys[index] = e.Value.(*gListMapNode).key
   298  		index++
   299  		return true
   300  	})
   301  	m.mu.RUnlock()
   302  	return keys
   303  }
   304  
   305  // Values returns all values of the map as a slice.
   306  func (m *ListMap) Values() []interface{} {
   307  	m.mu.RLock()
   308  	values := make([]interface{}, m.list.Len())
   309  	index := 0
   310  	m.list.IteratorAsc(func(e *glist.Element) bool {
   311  		values[index] = e.Value.(*gListMapNode).value
   312  		index++
   313  		return true
   314  	})
   315  	m.mu.RUnlock()
   316  	return values
   317  }
   318  
   319  // Contains checks whether a key exists.
   320  // It returns true if the <key> exists, or else false.
   321  func (m *ListMap) Contains(key interface{}) (ok bool) {
   322  	m.mu.RLock()
   323  	_, ok = m.data[key]
   324  	m.mu.RUnlock()
   325  	return
   326  }
   327  
   328  // Size returns the size of the map.
   329  func (m *ListMap) Size() (size int) {
   330  	m.mu.RLock()
   331  	size = len(m.data)
   332  	m.mu.RUnlock()
   333  	return
   334  }
   335  
   336  // IsEmpty checks whether the map is empty.
   337  // It returns true if map is empty, or else false.
   338  func (m *ListMap) IsEmpty() bool {
   339  	return m.Size() == 0
   340  }
   341  
   342  // Flip exchanges key-value of the map to value-key.
   343  func (m *ListMap) Flip() {
   344  	data := m.Map()
   345  	m.Clear()
   346  	for key, value := range data {
   347  		m.Set(value, key)
   348  	}
   349  }
   350  
   351  // Merge merges two link maps.
   352  // The <other> map will be merged into the map <m>.
   353  func (m *ListMap) Merge(other *ListMap) {
   354  	m.mu.Lock()
   355  	defer m.mu.Unlock()
   356  	if other != m {
   357  		other.mu.RLock()
   358  		defer other.mu.RUnlock()
   359  	}
   360  	node := (*gListMapNode)(nil)
   361  	other.list.IteratorAsc(func(e *glist.Element) bool {
   362  		node = e.Value.(*gListMapNode)
   363  		if e, ok := m.data[node.key]; !ok {
   364  			m.data[node.key] = m.list.PushBack(&gListMapNode{node.key, node.value})
   365  		} else {
   366  			e.Value = &gListMapNode{node.key, node.value}
   367  		}
   368  		return true
   369  	})
   370  }
   371  
   372  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   373  func (m *ListMap) MarshalJSON() ([]byte, error) {
   374  	return json.Marshal(gconv.Map(m.Map()))
   375  }