github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  	"sync/atomic"
    14  	"time"
    15  )
    16  
    17  func main() {
    18  	// Does not work on 32-bits due to partially conservative GC.
    19  	// Try to enable when we have fully precise GC.
    20  	if runtime.GOARCH != "amd64" {
    21  		return
    22  	}
    23  	// Likewise for gccgo.
    24  	if runtime.Compiler == "gccgo" {
    25  		return
    26  	}
    27  	N := int32(100)
    28  	count := N
    29  	done := make([]bool, N)
    30  	for i := int32(0); i < N; i++ {
    31  		x := i // subject to tiny alloc
    32  		// the closure must be big enough to be combined
    33  		runtime.SetFinalizer(&x, func(p *int32) {
    34  			// Check that p points to the correct subobject of the tiny allocation.
    35  			// It's a bit tricky, because we can't capture another variable
    36  			// with the expected value (it would be combined as well).
    37  			if *p < 0 || *p >= N {
    38  				println("got", *p)
    39  				panic("corrupted")
    40  			}
    41  			if done[*p] {
    42  				println("got", *p)
    43  				panic("already finalized")
    44  			}
    45  			done[*p] = true
    46  			atomic.AddInt32(&count, -1)
    47  		})
    48  	}
    49  	for i := 0; i < 4; i++ {
    50  		runtime.GC()
    51  		time.Sleep(10 * time.Millisecond)
    52  	}
    53  	// Some of the finalizers may not be executed,
    54  	// if the outermost allocations are combined with something persistent.
    55  	// Currently 4 int32's are combined into a 16-byte block,
    56  	// ensure that most of them are finalized.
    57  	if count >= N/4 {
    58  		println(count, "out of", N, "finalizer are not called")
    59  		panic("not all finalizers are called")
    60  	}
    61  }
    62