github.com/etecs-ru/ristretto@v0.9.1/z/z.go (about)

     1  /*
     2   * Copyright 2019 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package z
    18  
    19  import (
    20  	"context"
    21  	"sync"
    22  
    23  	"github.com/zeebo/xxh3"
    24  )
    25  
    26  // TODO: Figure out a way to re-use memhash for the second uint64 hash, we
    27  //       already know that appending bytes isn't reliable for generating a
    28  //       second hash (see Ristretto PR #88).
    29  //
    30  //       We also know that while the Go runtime has a runtime memhash128
    31  //       function, it's not possible to use it to generate [2]uint64 or
    32  //       anything resembling a 128bit hash, even though that's exactly what
    33  //       we need in this situation.
    34  func KeyToHash(key interface{}) (uint64, uint64) {
    35  	if key == nil {
    36  		return 0, 0
    37  	}
    38  	switch k := key.(type) {
    39  	case uint64:
    40  		return k, 0
    41  	case string:
    42  		return MemHashString(k), xxh3.HashString(k)
    43  	case []byte:
    44  		return MemHash(k), xxh3.Hash(k)
    45  	case byte:
    46  		return uint64(k), 0
    47  	case int:
    48  		return uint64(k), 0
    49  	case int32:
    50  		return uint64(k), 0
    51  	case uint32:
    52  		return uint64(k), 0
    53  	case int64:
    54  		return uint64(k), 0
    55  	default:
    56  		panic("Key type not supported")
    57  	}
    58  }
    59  
    60  var (
    61  	dummyCloserChan <-chan struct{}
    62  	tmpDir          string
    63  )
    64  
    65  // Closer holds the two things we need to close a goroutine and wait for it to
    66  // finish: a chan to tell the goroutine to shut down, and a WaitGroup with
    67  // which to wait for it to finish shutting down.
    68  type Closer struct {
    69  	ctx     context.Context
    70  	cancel  context.CancelFunc
    71  	waiting sync.WaitGroup
    72  }
    73  
    74  // SetTmpDir sets the temporary directory for the temporary buffers.
    75  func SetTmpDir(dir string) {
    76  	tmpDir = dir
    77  }
    78  
    79  // NewCloser constructs a new Closer, with an initial count on the WaitGroup.
    80  func NewCloser(initial int) *Closer {
    81  	ret := &Closer{}
    82  	ret.ctx, ret.cancel = context.WithCancel(context.Background())
    83  	ret.waiting.Add(initial)
    84  	return ret
    85  }
    86  
    87  // AddRunning Add()'s delta to the WaitGroup.
    88  func (lc *Closer) AddRunning(delta int) {
    89  	lc.waiting.Add(delta)
    90  }
    91  
    92  // Ctx can be used to get a context, which would automatically get cancelled when Signal is called.
    93  func (lc *Closer) Ctx() context.Context {
    94  	if lc == nil {
    95  		return context.Background()
    96  	}
    97  	return lc.ctx
    98  }
    99  
   100  // Signal signals the HasBeenClosed signal.
   101  func (lc *Closer) Signal() {
   102  	// Todo(ibrahim): Change Signal to return error on next badger breaking change.
   103  	lc.cancel()
   104  }
   105  
   106  // HasBeenClosed gets signaled when Signal() is called.
   107  func (lc *Closer) HasBeenClosed() <-chan struct{} {
   108  	if lc == nil {
   109  		return dummyCloserChan
   110  	}
   111  	return lc.ctx.Done()
   112  }
   113  
   114  // Done calls Done() on the WaitGroup.
   115  func (lc *Closer) Done() {
   116  	if lc == nil {
   117  		return
   118  	}
   119  	lc.waiting.Done()
   120  }
   121  
   122  // Wait waits on the WaitGroup. (It waits for NewCloser's initial value, AddRunning, and Done
   123  // calls to balance out.)
   124  func (lc *Closer) Wait() {
   125  	lc.waiting.Wait()
   126  }
   127  
   128  // SignalAndWait calls Signal(), then Wait().
   129  func (lc *Closer) SignalAndWait() {
   130  	lc.Signal()
   131  	lc.Wait()
   132  }
   133  
   134  // ZeroOut zeroes out all the bytes in the range [start, end).
   135  func ZeroOut(dst []byte, start, end int) {
   136  	if start < 0 || start >= len(dst) {
   137  		return // BAD
   138  	}
   139  	if end >= len(dst) {
   140  		end = len(dst)
   141  	}
   142  	if end-start <= 0 {
   143  		return
   144  	}
   145  	Memclr(dst[start:end])
   146  	// b := dst[start:end]
   147  	// for i := range b {
   148  	// 	b[i] = 0x0
   149  	// }
   150  }