Add Lockfile.AssertLocked and AssertLockedForWriting
This will replace Lockfile.Locked for the sanity-checking purposes. It is, just like Locked never was, NOT a way for a caller to check the current state. Hence the panic() instead of an error return. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
parent
db44035e3c
commit
5791b9d6af
|
|
@ -42,6 +42,14 @@ type Locker interface {
|
|||
|
||||
// Locked() checks if lock is locked for writing by a thread in this process
|
||||
Locked() bool
|
||||
|
||||
// AssertLocked() can be used by callers that _know_ that they hold the lock (for reading or writing), for sanity checking.
|
||||
// It might do nothing at all, or it may panic if the caller is not the owner of this lock.
|
||||
AssertLocked()
|
||||
|
||||
// AssertLocked() can be used by callers that _know_ that they hold the lock locked for writing, for sanity checking.
|
||||
// It might do nothing at all, or it may panic if the caller is not the owner of this lock for writing.
|
||||
AssertLockedForWriting()
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -220,6 +220,35 @@ func (l *lockfile) Locked() bool {
|
|||
return l.locked && (l.locktype == unix.F_WRLCK)
|
||||
}
|
||||
|
||||
func (l *lockfile) AssertLocked() {
|
||||
// DO NOT provide a variant that returns the value of l.locked.
|
||||
//
|
||||
// If the caller does not hold the lock, l.locked might nevertheless be true because another goroutine does hold it, and
|
||||
// we can’t tell the difference.
|
||||
//
|
||||
// Hence, this “AssertLocked” method, which exists only for sanity checks.
|
||||
|
||||
// Don’t even bother with l.stateMutex: The caller is expected to hold the lock, and in that case l.locked is constant true
|
||||
// with no possible writers.
|
||||
// If the caller does not hold the lock, we are violating the locking/memory model anyway, and accessing the data
|
||||
// without the lock is more efficient for callers, and potentially more visible to lock analysers for incorrect callers.
|
||||
if !l.locked {
|
||||
panic("internal error: lock is not held by the expected owner")
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lockfile) AssertLockedForWriting() {
|
||||
// DO NOT provide a variant that returns the current lock state.
|
||||
//
|
||||
// The same caveats as for AssertLocked apply equally.
|
||||
|
||||
l.AssertLocked()
|
||||
// Like AssertLocked, don’t even bother with l.stateMutex.
|
||||
if l.locktype != unix.F_WRLCK {
|
||||
panic("internal error: lock is not held for writing")
|
||||
}
|
||||
}
|
||||
|
||||
// Touch updates the lock file with the UID of the user.
|
||||
func (l *lockfile) Touch() error {
|
||||
l.stateMutex.Lock()
|
||||
|
|
|
|||
|
|
@ -51,6 +51,25 @@ func (l *lockfile) Locked() bool {
|
|||
return l.locked
|
||||
}
|
||||
|
||||
func (l *lockfile) AssertLocked() {
|
||||
// DO NOT provide a variant that returns the value of l.locked.
|
||||
//
|
||||
// If the caller does not hold the lock, l.locked might nevertheless be true because another goroutine does hold it, and
|
||||
// we can’t tell the difference.
|
||||
//
|
||||
// Hence, this “AssertLocked” method, which exists only for sanity checks.
|
||||
if !l.locked {
|
||||
panic("internal error: lock is not held by the expected owner")
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lockfile) AssertLockedForWriting() {
|
||||
// DO NOT provide a variant that returns the current lock state.
|
||||
//
|
||||
// The same caveats as for AssertLocked apply equally.
|
||||
l.AssertLocked() // The current implementation does not distinguish between read and write locks.
|
||||
}
|
||||
|
||||
func (l *lockfile) Modified() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue