github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/ingester/locker.go (about)

     1  package ingester
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  
     7  	"github.com/prometheus/common/model"
     8  
     9  	"github.com/cortexproject/cortex/pkg/util"
    10  )
    11  
    12  const (
    13  	cacheLineSize = 64
    14  )
    15  
    16  // Avoid false sharing when using array of mutexes.
    17  type paddedMutex struct {
    18  	sync.Mutex
    19  	//nolint:structcheck,unused
    20  	pad [cacheLineSize - unsafe.Sizeof(sync.Mutex{})]byte
    21  }
    22  
    23  // fingerprintLocker allows locking individual fingerprints. To limit the number
    24  // of mutexes needed for that, only a fixed number of mutexes are
    25  // allocated. Fingerprints to be locked are assigned to those pre-allocated
    26  // mutexes by their value. Collisions are not detected. If two fingerprints get
    27  // assigned to the same mutex, only one of them can be locked at the same
    28  // time. As long as the number of pre-allocated mutexes is much larger than the
    29  // number of goroutines requiring a fingerprint lock concurrently, the loss in
    30  // efficiency is small. However, a goroutine must never lock more than one
    31  // fingerprint at the same time. (In that case a collision would try to acquire
    32  // the same mutex twice).
    33  type fingerprintLocker struct {
    34  	fpMtxs    []paddedMutex
    35  	numFpMtxs uint32
    36  }
    37  
    38  // newFingerprintLocker returns a new fingerprintLocker ready for use.  At least
    39  // 1024 preallocated mutexes are used, even if preallocatedMutexes is lower.
    40  func newFingerprintLocker(preallocatedMutexes int) *fingerprintLocker {
    41  	if preallocatedMutexes < 1024 {
    42  		preallocatedMutexes = 1024
    43  	}
    44  	return &fingerprintLocker{
    45  		make([]paddedMutex, preallocatedMutexes),
    46  		uint32(preallocatedMutexes),
    47  	}
    48  }
    49  
    50  // Lock locks the given fingerprint.
    51  func (l *fingerprintLocker) Lock(fp model.Fingerprint) {
    52  	l.fpMtxs[util.HashFP(fp)%l.numFpMtxs].Lock()
    53  }
    54  
    55  // Unlock unlocks the given fingerprint.
    56  func (l *fingerprintLocker) Unlock(fp model.Fingerprint) {
    57  	l.fpMtxs[util.HashFP(fp)%l.numFpMtxs].Unlock()
    58  }