modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/tinyfin.go (about) 1 // run 2 3 // Copyright 2014 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Test finalizers work for tiny (combined) allocations. 8 9 package main 10 11 import ( 12 "runtime" 13 "time" 14 ) 15 16 func main() { 17 // Does not work on gccgo due to partially conservative GC. 18 // Try to enable when we have fully precise GC. 19 if runtime.Compiler == "gccgo" { 20 return 21 } 22 const N = 100 23 finalized := make(chan int32, N) 24 for i := 0; i < N; i++ { 25 x := new(int32) // subject to tiny alloc 26 *x = int32(i) 27 // the closure must be big enough to be combined 28 runtime.SetFinalizer(x, func(p *int32) { 29 finalized <- *p 30 }) 31 } 32 runtime.GC() 33 count := 0 34 done := make([]bool, N) 35 timeout := time.After(5*time.Second) 36 for { 37 select { 38 case <-timeout: 39 println("timeout,", count, "finalized so far") 40 panic("not all finalizers are called") 41 case x := <-finalized: 42 // Check that p points to the correct subobject of the tiny allocation. 43 // It's a bit tricky, because we can't capture another variable 44 // with the expected value (it would be combined as well). 45 if x < 0 || x >= N { 46 println("got", x) 47 panic("corrupted") 48 } 49 if done[x] { 50 println("got", x) 51 panic("already finalized") 52 } 53 done[x] = true 54 count++ 55 if count > N/10*9 { 56 // Some of the finalizers may not be executed, 57 // if the outermost allocations are combined with something persistent. 58 // Currently 4 int32's are combined into a 16-byte block, 59 // ensure that most of them are finalized. 60 return 61 } 62 } 63 } 64 }