github.com/fufuok/utils@v1.0.10/xsync/util_hash.go (about)

     1  package xsync
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  )
     7  
     8  // makeSeed creates a random seed.
     9  func makeSeed() uint64 {
    10  	var s1 uint32
    11  	for {
    12  		s1 = runtime_fastrand()
    13  		// We use seed 0 to indicate an uninitialized seed/hash,
    14  		// so keep trying until we get a non-zero seed.
    15  		if s1 != 0 {
    16  			break
    17  		}
    18  	}
    19  	s2 := runtime_fastrand()
    20  	return uint64(s1)<<32 | uint64(s2)
    21  }
    22  
    23  // hashString calculates a hash of s with the given seed.
    24  func hashString(s string, seed uint64) uint64 {
    25  	if s == "" {
    26  		return seed
    27  	}
    28  	strh := (*reflect.StringHeader)(unsafe.Pointer(&s))
    29  	return uint64(runtime_memhash(unsafe.Pointer(strh.Data), uintptr(seed), uintptr(strh.Len)))
    30  }
    31  
    32  //go:noescape
    33  //go:linkname runtime_memhash runtime.memhash
    34  func runtime_memhash(p unsafe.Pointer, h, s uintptr) uintptr
    35  
    36  // how interface is represented in memory
    37  type iface struct {
    38  	typ  uintptr
    39  	word unsafe.Pointer
    40  }
    41  
    42  // same as runtime_typehash, but always returns a uint64
    43  // see: maphash.rthash function for details
    44  func runtime_typehash64(t uintptr, p unsafe.Pointer, seed uint64) uint64 {
    45  	if unsafe.Sizeof(uintptr(0)) == 8 {
    46  		return uint64(runtime_typehash(t, p, uintptr(seed)))
    47  	}
    48  
    49  	lo := runtime_typehash(t, p, uintptr(seed))
    50  	hi := runtime_typehash(t, p, uintptr(seed>>32))
    51  	return uint64(hi)<<32 | uint64(lo)
    52  }
    53  
    54  //go:noescape
    55  //go:linkname runtime_typehash runtime.typehash
    56  func runtime_typehash(t uintptr, p unsafe.Pointer, h uintptr) uintptr