-
Notifications
You must be signed in to change notification settings - Fork 45
/
ref.go
53 lines (46 loc) · 1.26 KB
/
ref.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package utils
import "sync"
// RefCountedValue is a utility to "reference count" values in order
// to destruct them once no one references them.
// If you don't require that kind of logic, just rely on golang's
// garbage collection.
type RefCountedValue interface {
// Ref increments the reference count and returns the value.
Ref() interface{}
// Deref decrements the reference count and returns if this
// dereference resulted in the value being unreferenced.
Deref() (unreferenced bool)
}
type refCountedValue struct {
mu sync.Mutex
count int
val interface{}
}
// NewRefCountedValue returns a new reference counted value for the given
// value. Its reference count starts at zero but is not released. It is
// assumed the caller of this will reference it at least once.
func NewRefCountedValue(val interface{}) RefCountedValue {
return &refCountedValue{val: val}
}
func (rcv *refCountedValue) Ref() interface{} {
rcv.mu.Lock()
defer rcv.mu.Unlock()
if rcv.count == -1 {
panic("already released")
}
rcv.count++
return rcv.val
}
func (rcv *refCountedValue) Deref() bool {
rcv.mu.Lock()
defer rcv.mu.Unlock()
if rcv.count <= 0 {
panic("deref when count already zero")
}
rcv.count--
if rcv.count == 0 {
rcv.count = -1
return true
}
return false
}