github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/cache/refcnt_tracing.go (about)

     1  // Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  //go:build tracing
     6  // +build tracing
     7  
     8  package cache
     9  
    10  import (
    11  	"fmt"
    12  	"runtime/debug"
    13  	"strings"
    14  	"sync"
    15  	"sync/atomic"
    16  )
    17  
    18  // refcnt provides an atomic reference count, along with a tracing facility for
    19  // debugging logic errors in manipulating the reference count. This version is
    20  // used when the "tracing" build tag is enabled.
    21  type refcnt struct {
    22  	val atomic.Int32
    23  	sync.Mutex
    24  	msgs []string
    25  }
    26  
    27  func (v *refcnt) init(val int32) {
    28  	v.val.Store(val)
    29  	v.trace("init")
    30  }
    31  
    32  func (v *refcnt) refs() int32 {
    33  	return v.val.Load()
    34  }
    35  
    36  func (v *refcnt) acquire() {
    37  	switch n := v.val.Add(1); {
    38  	case n <= 1:
    39  		panic(fmt.Sprintf("pebble: inconsistent reference count: %d", n))
    40  	}
    41  	v.trace("acquire")
    42  }
    43  
    44  func (v *refcnt) release() bool {
    45  	n := v.val.Add(-1)
    46  	switch {
    47  	case n < 0:
    48  		panic(fmt.Sprintf("pebble: inconsistent reference count: %d", n))
    49  	}
    50  	v.trace("release")
    51  	return n == 0
    52  }
    53  
    54  func (v *refcnt) trace(msg string) {
    55  	s := fmt.Sprintf("%s: refs=%d\n%s", msg, v.refs(), debug.Stack())
    56  	v.Lock()
    57  	v.msgs = append(v.msgs, s)
    58  	v.Unlock()
    59  }
    60  
    61  func (v *refcnt) traces() string {
    62  	v.Lock()
    63  	s := strings.Join(v.msgs, "\n")
    64  	v.Unlock()
    65  	return s
    66  }