Line data Source code
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 invariants || race 6 : 7 : package invariants 8 : 9 : // CloseChecker is used to check that objects are closed exactly once. It is 10 : // empty and does nothing in non-invariant builds. 11 : // 12 : // Note that in non-invariant builds, the struct is zero-sized but it can still 13 : // increase the size of a parent struct if it is the last field (because Go must 14 : // allow getting a valid pointer address of the field). 15 : type CloseChecker struct { 16 : closed bool 17 : } 18 : 19 : // Close panics if called twice on the same object (if we were built with the 20 : // "invariants" or "race" build tags). 21 1 : func (d *CloseChecker) Close() { 22 1 : if d.closed { 23 0 : // Note: to debug a double-close, you can add a stack field to CloseChecker 24 0 : // and set it to string(debug.Stack()) in Close, then print that in this 25 0 : // panic. 26 0 : panic("double close") 27 : } 28 1 : d.closed = true 29 : } 30 : 31 : // AssertClosed panics in invariant builds if Close was not called. 32 0 : func (d *CloseChecker) AssertClosed() { 33 0 : if !d.closed { 34 0 : panic("not closed") 35 : } 36 : } 37 : 38 : // AssertNotClosed panics in invariant builds if Close was called. 39 0 : func (d *CloseChecker) AssertNotClosed() { 40 0 : if d.closed { 41 0 : panic("closed") 42 : } 43 : } 44 : 45 : // Value is a generic container for a value that should only exist in invariant 46 : // builds. In non-invariant builds, storing a value is a no-op, retrieving a 47 : // value returns the type parameter's zero value, and the Value struct takes up 48 : // no space. 49 : // 50 : // Note that in non-invariant builds, the struct is zero-sized but it can still 51 : // increase the size of a parent struct if it is the last field (because Go must 52 : // allow getting a valid pointer address of the field). 53 : type Value[V any] struct { 54 : v V 55 : } 56 : 57 : // Get the current value, or the zero-value if invariants are disabled. 58 1 : func (v *Value[V]) Get() V { 59 1 : return v.v 60 1 : } 61 : 62 : // Set the value; no-op in non-invariant builds. 63 1 : func (v *Value[V]) Set(inner V) { 64 1 : v.v = inner 65 1 : }