1// run
2
3// Copyright 2013 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
7package main
8
9import (
10	"runtime"
11	"sync"
12	"sync/atomic"
13	"time"
14)
15
16const N = 10
17
18var count int64
19
20func run() error {
21	f1 := func() {}
22	f2 := func() {
23		func() {
24			f1()
25		}()
26	}
27	runtime.SetFinalizer(&f1, func(f *func()) {
28		atomic.AddInt64(&count, -1)
29	})
30	go f2()
31	return nil
32}
33
34func main() {
35	// Does not work with gccgo, due to partially conservative GC.
36	// Try to enable when we have fully precise GC.
37	if runtime.Compiler == "gccgo" {
38		return
39	}
40	count = N
41	var wg sync.WaitGroup
42	wg.Add(N)
43	for i := 0; i < N; i++ {
44		go func() {
45			run()
46			wg.Done()
47		}()
48	}
49	wg.Wait()
50	for i := 0; i < 2*N; i++ {
51		time.Sleep(10 * time.Millisecond)
52		runtime.GC()
53	}
54	if count != 0 {
55		println(count, "out of", N, "finalizer are not called")
56		panic("not all finalizers are called")
57	}
58}
59