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

lightningnetwork / lnd / 13674605784

05 Mar 2025 11:09AM UTC coverage: 56.607% (-12.0%) from 68.655%
13674605784

Pull #9581

github

web-flow
Merge a116eef5e into 9feb761b4
Pull Request #9581: tor: fix `TestReconnectSucceed`

104674 of 184913 relevant lines covered (56.61%)

24195.64 hits per line

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

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

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

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

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