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

lightningnetwork / lnd / 14193549836

01 Apr 2025 10:40AM UTC coverage: 69.046% (+0.007%) from 69.039%
14193549836

Pull #9665

github

web-flow
Merge e8825f209 into b01f4e514
Pull Request #9665: kvdb: bump etcd libs to v3.5.12

133439 of 193262 relevant lines covered (69.05%)

22119.45 hits per line

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

100.0
/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] {
1,207✔
31
        return &Mutex[T]{
1,207✔
32
                mutexes: make(map[T]*cntMutex),
1,207✔
33
        }
1,207✔
34
}
1,207✔
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,971✔
39
        c.mapMtx.Lock()
2,971✔
40
        mtx, ok := c.mutexes[id]
2,971✔
41
        if ok {
3,173✔
42
                // If the mutex already existed in the map, we increment its
202✔
43
                // counter, to indicate that there now is one more goroutine
202✔
44
                // waiting for it.
202✔
45
                mtx.cnt++
202✔
46
        } else {
2,974✔
47
                // If it was not in the map, it means no other goroutine has
2,772✔
48
                // locked the mutex for this ID, and we can create a new mutex
2,772✔
49
                // with count 1 and add it to the map.
2,772✔
50
                mtx = &cntMutex{
2,772✔
51
                        cnt: 1,
2,772✔
52
                }
2,772✔
53
                c.mutexes[id] = mtx
2,772✔
54
        }
2,772✔
55
        c.mapMtx.Unlock()
2,971✔
56

2,971✔
57
        // Acquire the mutex for this ID.
2,971✔
58
        mtx.Lock()
2,971✔
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,973✔
64
        // Since we are done with all the work for this update, we update the
2,973✔
65
        // map to reflect that.
2,973✔
66
        c.mapMtx.Lock()
2,973✔
67

2,973✔
68
        mtx, ok := c.mutexes[id]
2,973✔
69
        if !ok {
2,975✔
70
                // The mutex not existing in the map means an unlock for an ID
2✔
71
                // not currently locked was attempted.
2✔
72
                panic(fmt.Sprintf("double unlock for id %v",
2✔
73
                        id))
2✔
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,971✔
82
        if mtx.cnt == 0 {
5,743✔
83
                delete(c.mutexes, id)
2,772✔
84
        }
2,772✔
85
        c.mapMtx.Unlock()
2,971✔
86

2,971✔
87
        // Unlock the mutex for this ID.
2,971✔
88
        mtx.Unlock()
2,971✔
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