summaryrefslogtreecommitdiffhomepage
path: root/util/ctxlock/mutex.go
diff options
context:
space:
mode:
Diffstat (limited to 'util/ctxlock/mutex.go')
-rw-r--r--util/ctxlock/mutex.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/util/ctxlock/mutex.go b/util/ctxlock/mutex.go
new file mode 100644
index 000000000..3d00ef7e6
--- /dev/null
+++ b/util/ctxlock/mutex.go
@@ -0,0 +1,45 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package ctxlock
+
+import (
+ "sync"
+)
+
+// mutex is a wrapper around [sync.Mutex] that associates a [Rank] with the mutex
+// and provides storage for an arbitrary value (of type S) to be used by the state
+// that owns the lock while it is held. It's exported as [Mutex] in the package API.
+type mutex[R Rank, S any] struct {
+ // r is the rank of the mutex, used to check lock order.
+ r R
+ // m is the underlying mutex that provides the locking mechanism.
+ m sync.Mutex
+ // lockState is a memory region used by the state that owns the lock while it is held.
+ // It serves as pre-allocated lockState to avoid (in the [unchecked] case)
+ // or reduce (in the [checked] case) memory allocations.
+ lockState S
+}
+
+func (m *mutex[R, S]) rank() Rank {
+ return m.r
+}
+
+func (m *mutex[R, S]) lock() {
+ m.m.Lock()
+}
+
+func (m *mutex[R, S]) state() any {
+ return &m.lockState
+}
+
+func (m *mutex[R, S]) unlock() {
+ m.m.Unlock()
+}
+
+// mutexHandle is a subset of the [mutex] methods that are used once the mutex is locked.
+type mutexHandle interface {
+ rank() Rank
+ state() any
+ unlock()
+}