зеркало из https://github.com/CryptoPro/go.git
65 строки
1.6 KiB
Go
65 строки
1.6 KiB
Go
// run
|
|
|
|
// Copyright 2014 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test finalizers work for tiny (combined) allocations.
|
|
|
|
package main
|
|
|
|
import (
|
|
"runtime"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
// Does not work on gccgo due to partially conservative GC.
|
|
// Try to enable when we have fully precise GC.
|
|
if runtime.Compiler == "gccgo" {
|
|
return
|
|
}
|
|
const N = 100
|
|
finalized := make(chan int32, N)
|
|
for i := 0; i < N; i++ {
|
|
x := new(int32) // subject to tiny alloc
|
|
*x = int32(i)
|
|
// the closure must be big enough to be combined
|
|
runtime.SetFinalizer(x, func(p *int32) {
|
|
finalized <- *p
|
|
})
|
|
}
|
|
runtime.GC()
|
|
count := 0
|
|
done := make([]bool, N)
|
|
timeout := time.After(5*time.Second)
|
|
for {
|
|
select {
|
|
case <-timeout:
|
|
println("timeout,", count, "finalized so far")
|
|
panic("not all finalizers are called")
|
|
case x := <-finalized:
|
|
// Check that p points to the correct subobject of the tiny allocation.
|
|
// It's a bit tricky, because we can't capture another variable
|
|
// with the expected value (it would be combined as well).
|
|
if x < 0 || x >= N {
|
|
println("got", x)
|
|
panic("corrupted")
|
|
}
|
|
if done[x] {
|
|
println("got", x)
|
|
panic("already finalized")
|
|
}
|
|
done[x] = true
|
|
count++
|
|
if count > N/10*9 {
|
|
// Some of the finalizers may not be executed,
|
|
// if the outermost allocations are combined with something persistent.
|
|
// Currently 4 int32's are combined into a 16-byte block,
|
|
// ensure that most of them are finalized.
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|