| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | // run | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Copyright 2013 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 that defers do not prevent garbage collection. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 	"sync/atomic" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var sink func() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	// Does not work on 32-bits due to partially conservative GC. | 
					
						
							|  |  |  | 	// Try to enable when we have fully precise GC. | 
					
						
							|  |  |  | 	if runtime.GOARCH != "amd64" { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-12-12 17:13:27 -08:00
										 |  |  | 	// Likewise for gccgo. | 
					
						
							|  |  |  | 	if runtime.Compiler == "gccgo" { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | 	N := 10 | 
					
						
							|  |  |  | 	count := int32(N) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	wg.Add(N) | 
					
						
							|  |  |  | 	for i := 0; i < N; i++ { | 
					
						
							|  |  |  | 		go func() { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2014-01-24 22:35:11 +04:00
										 |  |  | 			v := new(string) | 
					
						
							| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | 			f := func() { | 
					
						
							| 
									
										
										
										
											2014-01-24 22:35:11 +04:00
										 |  |  | 				if *v != "" { | 
					
						
							| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | 					panic("oops") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-01-24 22:35:11 +04:00
										 |  |  | 			if *v != "" { | 
					
						
							| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | 				// let the compiler think f escapes | 
					
						
							|  |  |  | 				sink = f | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-01-24 22:35:11 +04:00
										 |  |  | 			runtime.SetFinalizer(v, func(p *string) { | 
					
						
							| 
									
										
										
										
											2013-07-01 17:36:08 -04:00
										 |  |  | 				atomic.AddInt32(&count, -1) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			defer f() | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 	for i := 0; i < 3; i++ { | 
					
						
							|  |  |  | 		time.Sleep(10 * time.Millisecond) | 
					
						
							|  |  |  | 		runtime.GC() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if count != 0 { | 
					
						
							|  |  |  | 		println(count, "out of", N, "finalizer are not called") | 
					
						
							|  |  |  | 		panic("not all finalizers are called") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |