Commit ac802560 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent e39e6682
......@@ -68,7 +68,7 @@ type Ref struct {
state weakRefState
}
//trace:event traceRelease(w *Ref, released bool)
//trace:event traceRelease(w *Ref)
// NewRef creates new weak reference pointing to obj.
//
......@@ -100,11 +100,10 @@ func NewRef(obj interface{}) *Ref {
if w.state == objGot {
w.state = objLive
runtime.SetFinalizer(obj, release)
traceRelease(w, false)
} else {
w.state = objReleased
traceRelease(w, true)
}
traceRelease(w)
w.mu.Unlock()
}
......
......@@ -56,20 +56,27 @@ func TestIface(t *testing.T) {
}
func TestWeakRef(t *testing.T) {
for i := 0; i < 100; i++ {
println(i)
testWeakRef(t)
}
}
func testWeakRef(t *testing.T) {
type T struct{ _ [8]int64 } // large enough not to go into tinyalloc
p := new(T)
w := NewRef(p)
pptr := uintptr(unsafe.Pointer(p))
wrelease := make(chan bool) // events from traceRelease(w)
wrelease := make(chan weakRefState) // w.state from traceRelease(w) event
tpg := &tracing.ProbeGroup{}
tracing.Lock()
traceRelease_Attach(tpg, func(w_ *Ref, released bool) {
traceRelease_Attach(tpg, func(w_ *Ref) {
if w_ != w {
panic("release: w != w_")
}
wrelease <- released
wrelease <- w.state
})
traceGotPre_Attach(tpg, func(w *Ref) {
// nop for now
......@@ -86,20 +93,10 @@ func TestWeakRef(t *testing.T) {
}
// perform GC + give finalizers a chance to run.
GC := func(expectRelease bool) {
GCnofin := func() {
t.Helper()
runtime.GC()
// GC only queues finalizers, not runs them directly. Give it
// some time so that finalizers could have been run.
if expectRelease {
select {
case <-wrelease:
// ok
case <-time.After(100 * time.Millisecond):
t.Fatal("no release event")
}
} else {
select {
case <-time.After(10 * time.Millisecond):
// ok
......@@ -107,19 +104,36 @@ func TestWeakRef(t *testing.T) {
t.Fatal("unexpected release event")
}
}
GCfin := func(stateOK weakRefState) {
t.Helper()
runtime.GC()
// GC only queues finalizers, not runs them directly. Give it
// some time so that finalizers could have been run.
var state weakRefState
select {
case state = <-wrelease:
// ok
case <-time.After(1 * time.Second):
t.Fatal("no release event")
}
if state != stateOK {
t.Fatalf("release: state != stateOK; state=%v stateOK=%v", state, stateOK)
}
}
assertEq(w.state, objLive)
assertEq(w.Get(), p)
assertEq(w.state, objGot)
GC(false)
GCnofin()
assertEq(w.state, objGot) // fin has not been run at all (p is live)
assertEq(w.Get(), p)
assertEq(w.state, objGot)
p = nil
GC(true)
assertEq(w.state, objLive) // fin ran and downgraded got -> live
GCfin(objLive) // fin ran and downgraded got -> live
assertEq(w.state, objLive)
switch p_ := w.Get().(type) {
default:
t.Fatalf("Get after objGot -> objLive: %#v", p_)
......@@ -130,10 +144,8 @@ func TestWeakRef(t *testing.T) {
}
assertEq(w.state, objGot)
GC(true)
assertEq(w.state, objLive) // fin ran again and again downgraded got -> live
GCfin(objLive) // fin ran again and again downgraded got -> live
GC(true)
assertEq(w.state, objReleased) // fin ran again and released the object
GCfin(objReleased) // fin ran again and released the object
assertEq(w.Get(), nil)
}
......@@ -35,32 +35,32 @@ func traceGotPre_Attach(pg *tracing.ProbeGroup, probe func(w *Ref)) *tracing.Pro
return &p.Probe
}
// traceevent: traceRelease(w *Ref, released bool)
// traceevent: traceRelease(w *Ref)
type _t_traceRelease struct {
tracing.Probe
probefunc func(w *Ref, released bool)
probefunc func(w *Ref)
}
var _traceRelease *_t_traceRelease
func traceRelease(w *Ref, released bool) {
func traceRelease(w *Ref) {
if _traceRelease != nil {
_traceRelease_run(w, released)
_traceRelease_run(w)
}
}
func _traceRelease_run(w *Ref, released bool) {
func _traceRelease_run(w *Ref) {
for p := _traceRelease; p != nil; p = (*_t_traceRelease)(unsafe.Pointer(p.Next())) {
p.probefunc(w, released)
p.probefunc(w)
}
}
func traceRelease_Attach(pg *tracing.ProbeGroup, probe func(w *Ref, released bool)) *tracing.Probe {
func traceRelease_Attach(pg *tracing.ProbeGroup, probe func(w *Ref)) *tracing.Probe {
p := _t_traceRelease{probefunc: probe}
tracing.AttachProbe(pg, (**tracing.Probe)(unsafe.Pointer(&_traceRelease)), &p.Probe)
return &p.Probe
}
// trace export signature
func _trace_exporthash_c65df3d81975319429a288a09095370dace6a87b() {}
func _trace_exporthash_55416cf1cbcad92c4b4497269fa14b46e82469bd() {}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment