github.com/m3db/m3@v1.5.0/src/metrics/matcher/cache/elem_map_gen.go (about)

     1  // Copyright (c) 2021 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  // This file was automatically generated by genny.
    22  // Any changes will be lost if this file is regenerated.
    23  // see https://github.com/mauricelam/genny
    24  
    25  package cache
    26  
    27  // Copyright (c) 2021 Uber Technologies, Inc.
    28  //
    29  // Permission is hereby granted, free of charge, to any person obtaining a copy
    30  // of this software and associated documentation files (the "Software"), to deal
    31  // in the Software without restriction, including without limitation the rights
    32  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    33  // copies of the Software, and to permit persons to whom the Software is
    34  // furnished to do so, subject to the following conditions:
    35  //
    36  // The above copyright notice and this permission notice shall be included in
    37  // all copies or substantial portions of the Software.
    38  //
    39  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    40  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    41  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    42  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    43  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    44  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    45  // THE SOFTWARE.
    46  
    47  // This file was automatically generated by genny.
    48  // Any changes will be lost if this file is regenerated.
    49  // see https://github.com/mauricelam/genny
    50  
    51  // Copyright (c) 2018 Uber Technologies, Inc.
    52  //
    53  // Permission is hereby granted, free of charge, to any person obtaining a copy
    54  // of this software and associated documentation files (the "Software"), to deal
    55  // in the Software without restriction, including without limitation the rights
    56  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    57  // copies of the Software, and to permit persons to whom the Software is
    58  // furnished to do so, subject to the following conditions:
    59  //
    60  // The above copyright notice and this permission notice shall be included in
    61  // all copies or substantial portions of the Software.
    62  //
    63  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    64  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    65  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    66  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    67  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    68  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    69  // THE SOFTWARE.
    70  
    71  // elemMapHash is the hash for a given map entry, this is public to support
    72  // iterating over the map using a native Go for loop.
    73  type elemMapHash uint64
    74  
    75  // elemMapHashFn is the hash function to execute when hashing a key.
    76  type elemMapHashFn func([]byte) elemMapHash
    77  
    78  // elemMapEqualsFn is the equals key function to execute when detecting equality of a key.
    79  type elemMapEqualsFn func([]byte, []byte) bool
    80  
    81  // elemMapCopyFn is the copy key function to execute when copying the key.
    82  type elemMapCopyFn func([]byte) []byte
    83  
    84  // elemMapFinalizeFn is the finalize key function to execute when finished with a key.
    85  type elemMapFinalizeFn func([]byte)
    86  
    87  // elemMap uses the genny package to provide a generic hash map that can be specialized
    88  // by running the following command from this root of the repository:
    89  // ```
    90  // make hashmap-gen pkg=outpkg key_type=Type value_type=Type out_dir=/tmp
    91  // ```
    92  // Or if you would like to use bytes or ident.ID as keys you can use the
    93  // partially specialized maps to generate your own maps as well:
    94  // ```
    95  // make byteshashmap-gen pkg=outpkg value_type=Type out_dir=/tmp
    96  // make idhashmap-gen pkg=outpkg value_type=Type out_dir=/tmp
    97  // ```
    98  // This will output to stdout the generated source file to use for your map.
    99  // It uses linear probing by incrementing the number of the hash created when
   100  // hashing the identifier if there is a collision.
   101  // elemMap is a value type and not an interface to allow for less painful
   102  // upgrades when adding/removing methods, it is not likely to need mocking so
   103  // an interface would not be super useful either.
   104  type elemMap struct {
   105  	_elemMapOptions
   106  
   107  	// lookup uses hash of the identifier for the key and the MapEntry value
   108  	// wraps the value type and the key (used to ensure lookup is correct
   109  	// when dealing with collisions), we use uint64 for the hash partially
   110  	// because lookups of maps with uint64 keys has a fast path for Go.
   111  	lookup map[elemMapHash]elemMapEntry
   112  }
   113  
   114  // _elemMapOptions is a set of options used when creating an identifier map, it is kept
   115  // private so that implementers of the generated map can specify their own options
   116  // that partially fulfill these options.
   117  type _elemMapOptions struct {
   118  	// hash is the hash function to execute when hashing a key.
   119  	hash elemMapHashFn
   120  	// equals is the equals key function to execute when detecting equality.
   121  	equals elemMapEqualsFn
   122  	// copy is the copy key function to execute when copying the key.
   123  	copy elemMapCopyFn
   124  	// finalize is the finalize key function to execute when finished with a
   125  	// key, this is optional to specify.
   126  	finalize elemMapFinalizeFn
   127  	// initialSize is the initial size for the map, use zero to use Go's std map
   128  	// initial size and consequently is optional to specify.
   129  	initialSize int
   130  }
   131  
   132  // elemMapEntry is an entry in the map, this is public to support iterating
   133  // over the map using a native Go for loop.
   134  type elemMapEntry struct {
   135  	// key is used to check equality on lookups to resolve collisions
   136  	key _elemMapKey
   137  	// value type stored
   138  	value elementPtr
   139  }
   140  
   141  type _elemMapKey struct {
   142  	key      []byte
   143  	finalize bool
   144  }
   145  
   146  // Key returns the map entry key.
   147  func (e elemMapEntry) Key() []byte {
   148  	return e.key.key
   149  }
   150  
   151  // Value returns the map entry value.
   152  func (e elemMapEntry) Value() elementPtr {
   153  	return e.value
   154  }
   155  
   156  // _elemMapAlloc is a non-exported function so that when generating the source code
   157  // for the map you can supply a public constructor that sets the correct
   158  // hash, equals, copy, finalize options without users of the map needing to
   159  // implement them themselves.
   160  func _elemMapAlloc(opts _elemMapOptions) *elemMap {
   161  	m := &elemMap{_elemMapOptions: opts}
   162  	m.Reallocate()
   163  	return m
   164  }
   165  
   166  func (m *elemMap) newMapKey(k []byte, opts _elemMapKeyOptions) _elemMapKey {
   167  	key := _elemMapKey{key: k, finalize: opts.finalizeKey}
   168  	if !opts.copyKey {
   169  		return key
   170  	}
   171  
   172  	key.key = m.copy(k)
   173  	return key
   174  }
   175  
   176  func (m *elemMap) removeMapKey(hash elemMapHash, key _elemMapKey) {
   177  	delete(m.lookup, hash)
   178  	if key.finalize {
   179  		m.finalize(key.key)
   180  	}
   181  }
   182  
   183  // Get returns a value in the map for an identifier if found.
   184  func (m *elemMap) Get(k []byte) (elementPtr, bool) {
   185  	hash := m.hash(k)
   186  	for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] {
   187  		if m.equals(entry.key.key, k) {
   188  			return entry.value, true
   189  		}
   190  		// Linear probe to "next" to this entry (really a rehash)
   191  		hash++
   192  	}
   193  	var empty elementPtr
   194  	return empty, false
   195  }
   196  
   197  // Set will set the value for an identifier.
   198  func (m *elemMap) Set(k []byte, v elementPtr) {
   199  	m.set(k, v, _elemMapKeyOptions{
   200  		copyKey:     true,
   201  		finalizeKey: m.finalize != nil,
   202  	})
   203  }
   204  
   205  // elemMapSetUnsafeOptions is a set of options to use when setting a value with
   206  // the SetUnsafe method.
   207  type elemMapSetUnsafeOptions struct {
   208  	NoCopyKey     bool
   209  	NoFinalizeKey bool
   210  }
   211  
   212  // SetUnsafe will set the value for an identifier with unsafe options for how
   213  // the map treats the key.
   214  func (m *elemMap) SetUnsafe(k []byte, v elementPtr, opts elemMapSetUnsafeOptions) {
   215  	m.set(k, v, _elemMapKeyOptions{
   216  		copyKey:     !opts.NoCopyKey,
   217  		finalizeKey: !opts.NoFinalizeKey,
   218  	})
   219  }
   220  
   221  type _elemMapKeyOptions struct {
   222  	copyKey     bool
   223  	finalizeKey bool
   224  }
   225  
   226  func (m *elemMap) set(k []byte, v elementPtr, opts _elemMapKeyOptions) {
   227  	hash := m.hash(k)
   228  	for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] {
   229  		if m.equals(entry.key.key, k) {
   230  			m.lookup[hash] = elemMapEntry{
   231  				key:   entry.key,
   232  				value: v,
   233  			}
   234  			return
   235  		}
   236  		// Linear probe to "next" to this entry (really a rehash)
   237  		hash++
   238  	}
   239  
   240  	m.lookup[hash] = elemMapEntry{
   241  		key:   m.newMapKey(k, opts),
   242  		value: v,
   243  	}
   244  }
   245  
   246  // Iter provides the underlying map to allow for using a native Go for loop
   247  // to iterate the map, however callers should only ever read and not write
   248  // the map.
   249  func (m *elemMap) Iter() map[elemMapHash]elemMapEntry {
   250  	return m.lookup
   251  }
   252  
   253  // Len returns the number of map entries in the map.
   254  func (m *elemMap) Len() int {
   255  	return len(m.lookup)
   256  }
   257  
   258  // Contains returns true if value exists for key, false otherwise, it is
   259  // shorthand for a call to Get that doesn't return the value.
   260  func (m *elemMap) Contains(k []byte) bool {
   261  	_, ok := m.Get(k)
   262  	return ok
   263  }
   264  
   265  // Delete will remove a value set in the map for the specified key.
   266  func (m *elemMap) Delete(k []byte) {
   267  	hash := m.hash(k)
   268  	for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] {
   269  		if m.equals(entry.key.key, k) {
   270  			m.removeMapKey(hash, entry.key)
   271  			return
   272  		}
   273  		// Linear probe to "next" to this entry (really a rehash)
   274  		hash++
   275  	}
   276  }
   277  
   278  // Reset will reset the map by simply deleting all keys to avoid
   279  // allocating a new map.
   280  func (m *elemMap) Reset() {
   281  	for hash, entry := range m.lookup {
   282  		m.removeMapKey(hash, entry.key)
   283  	}
   284  }
   285  
   286  // Reallocate will avoid deleting all keys and reallocate a new
   287  // map, this is useful if you believe you have a large map and
   288  // will not need to grow back to a similar size.
   289  func (m *elemMap) Reallocate() {
   290  	if m.initialSize > 0 {
   291  		m.lookup = make(map[elemMapHash]elemMapEntry, m.initialSize)
   292  	} else {
   293  		m.lookup = make(map[elemMapHash]elemMapEntry)
   294  	}
   295  }