• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 14885280210

07 May 2025 01:59PM UTC coverage: 58.038% (-11.0%) from 68.992%
14885280210

Pull #9789

github

web-flow
Merge b72813120 into 67a40c90a
Pull Request #9789: multi: use updated TLV SizeFunc signature

3 of 6 new or added lines in 2 files covered. (50.0%)

29137 existing lines in 453 files now uncovered.

96491 of 166256 relevant lines covered (58.04%)

1.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.11
/multimutex/multimutex.go
1
package multimutex
2

3
import (
4
        "fmt"
5
        "sync"
6
)
7

8
// cntMutex is a struct that wraps a counter and a mutex, and is used to keep
9
// track of the number of goroutines waiting for access to the
10
// mutex, such that we can forget about it when the counter is zero.
11
type cntMutex struct {
12
        cnt int
13
        sync.Mutex
14
}
15

16
// Mutex is a struct that keeps track of a set of mutexes with a given ID. It
17
// can be used for making sure only one goroutine gets given the mutex per ID.
18
type Mutex[T comparable] struct {
19
        // mutexes is a map of IDs to a cntMutex. The cntMutex for a given ID
20
        // will hold the mutex to be used by all callers requesting access for
21
        // the ID, in addition to the count of callers.
22
        mutexes map[T]*cntMutex
23

24
        // mapMtx is used to give synchronize concurrent access to the mutexes
25
        // map.
26
        mapMtx sync.Mutex
27
}
28

29
// NewMutex creates a new Mutex.
30
func NewMutex[T comparable]() *Mutex[T] {
2✔
31
        return &Mutex[T]{
2✔
32
                mutexes: make(map[T]*cntMutex),
2✔
33
        }
2✔
34
}
2✔
35

36
// Lock locks the mutex by the given ID. If the mutex is already locked by this
37
// ID, Lock blocks until the mutex is available.
38
func (c *Mutex[T]) Lock(id T) {
2✔
39
        c.mapMtx.Lock()
2✔
40
        mtx, ok := c.mutexes[id]
2✔
41
        if ok {
4✔
42
                // If the mutex already existed in the map, we increment its
2✔
43
                // counter, to indicate that there now is one more goroutine
2✔
44
                // waiting for it.
2✔
45
                mtx.cnt++
2✔
46
        } else {
4✔
47
                // If it was not in the map, it means no other goroutine has
2✔
48
                // locked the mutex for this ID, and we can create a new mutex
2✔
49
                // with count 1 and add it to the map.
2✔
50
                mtx = &cntMutex{
2✔
51
                        cnt: 1,
2✔
52
                }
2✔
53
                c.mutexes[id] = mtx
2✔
54
        }
2✔
55
        c.mapMtx.Unlock()
2✔
56

2✔
57
        // Acquire the mutex for this ID.
2✔
58
        mtx.Lock()
2✔
59
}
60

61
// Unlock unlocks the mutex by the given ID. It is a run-time error if the
62
// mutex is not locked by the ID on entry to Unlock.
63
func (c *Mutex[T]) Unlock(id T) {
2✔
64
        // Since we are done with all the work for this update, we update the
2✔
65
        // map to reflect that.
2✔
66
        c.mapMtx.Lock()
2✔
67

2✔
68
        mtx, ok := c.mutexes[id]
2✔
69
        if !ok {
2✔
UNCOV
70
                // The mutex not existing in the map means an unlock for an ID
×
UNCOV
71
                // not currently locked was attempted.
×
UNCOV
72
                panic(fmt.Sprintf("double unlock for id %v",
×
UNCOV
73
                        id))
×
74
        }
75

76
        // Decrement the counter. If the count goes to zero, it means this
77
        // caller was the last one to wait for the mutex, and we can delete it
78
        // from the map. We can do this safely since we are under the mapMtx,
79
        // meaning that all other goroutines waiting for the mutex already have
80
        // incremented it, or will create a new mutex when they get the mapMtx.
81
        mtx.cnt--
2✔
82
        if mtx.cnt == 0 {
4✔
83
                delete(c.mutexes, id)
2✔
84
        }
2✔
85
        c.mapMtx.Unlock()
2✔
86

2✔
87
        // Unlock the mutex for this ID.
2✔
88
        mtx.Unlock()
2✔
89
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc