Russ Cox | 0b477ef | 2012-02-16 23:48:57 -0500 | [diff] [blame] | 1 | // run |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 2 | |
| 3 | // Copyright 2009 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 | |
Rob Pike | fc0dc04 | 2012-02-19 13:19:43 +1100 | [diff] [blame] | 7 | // Test the behavior of closures. |
| 8 | |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 9 | package main |
| 10 | |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 11 | import "runtime" |
| 12 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 13 | var c = make(chan int) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 14 | |
| 15 | func check(a []int) { |
| 16 | for i := 0; i < len(a); i++ { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 17 | n := <-c |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 18 | if n != a[i] { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 19 | println("want", a[i], "got", n, "at", i) |
| 20 | panic("fail") |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 21 | } |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | func f() { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 26 | var i, j int |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 27 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 28 | i = 1 |
| 29 | j = 2 |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 30 | f := func() { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 31 | c <- i |
| 32 | i = 4 |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 33 | g := func() { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 34 | c <- i |
| 35 | c <- j |
| 36 | } |
| 37 | g() |
| 38 | c <- i |
| 39 | } |
| 40 | j = 5 |
| 41 | f() |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 42 | } |
| 43 | |
| 44 | // Accumulator generator |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 45 | func accum(n int) func(int) int { |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 46 | return func(i int) int { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 47 | n += i |
| 48 | return n |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 49 | } |
| 50 | } |
| 51 | |
| 52 | func g(a, b func(int) int) { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 53 | c <- a(2) |
| 54 | c <- b(3) |
| 55 | c <- a(4) |
| 56 | c <- b(5) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | func h() { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 60 | var x8 byte = 100 |
| 61 | var x64 int64 = 200 |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 62 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 63 | c <- int(x8) |
| 64 | c <- int(x64) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 65 | f := func(z int) { |
| 66 | g := func() { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 67 | c <- int(x8) |
| 68 | c <- int(x64) |
| 69 | c <- z |
| 70 | } |
| 71 | g() |
| 72 | c <- int(x8) |
| 73 | c <- int(x64) |
| 74 | c <- int(z) |
| 75 | } |
| 76 | x8 = 101 |
| 77 | x64 = 201 |
| 78 | f(500) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 79 | } |
| 80 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 81 | func newfunc() func(int) int { return func(x int) int { return x } } |
Russ Cox | 9346c6d | 2009-07-28 20:01:00 -0700 | [diff] [blame] | 82 | |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 83 | func main() { |
Dmitriy Vyukov | 91e56e6 | 2012-07-01 21:59:50 +0400 | [diff] [blame] | 84 | runtime.GOMAXPROCS(1) |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 85 | var fail bool |
| 86 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 87 | go f() |
| 88 | check([]int{1, 4, 5, 4}) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 89 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 90 | a := accum(0) |
| 91 | b := accum(1) |
| 92 | go g(a, b) |
| 93 | check([]int{2, 4, 6, 9}) |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 94 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 95 | go h() |
| 96 | check([]int{100, 200, 101, 201, 500, 101, 201, 500}) |
Russ Cox | 9346c6d | 2009-07-28 20:01:00 -0700 | [diff] [blame] | 97 | |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 98 | memstats := new(runtime.MemStats) |
| 99 | runtime.ReadMemStats(memstats) |
| 100 | n0 := memstats.Mallocs |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 101 | |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 102 | x, y := newfunc(), newfunc() |
Russ Cox | 9346c6d | 2009-07-28 20:01:00 -0700 | [diff] [blame] | 103 | if x(1) != 1 || y(2) != 2 { |
Rob Pike | 325cf8e | 2010-03-24 16:46:53 -0700 | [diff] [blame] | 104 | println("newfunc returned broken funcs") |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 105 | fail = true |
| 106 | } |
| 107 | |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 108 | runtime.ReadMemStats(memstats) |
| 109 | if n0 != memstats.Mallocs { |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 110 | println("newfunc allocated unexpectedly") |
| 111 | fail = true |
Russ Cox | 9346c6d | 2009-07-28 20:01:00 -0700 | [diff] [blame] | 112 | } |
Russ Cox | 1b31c37 | 2010-12-13 16:51:19 -0500 | [diff] [blame] | 113 | |
| 114 | ff(1) |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 115 | |
| 116 | if fail { |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 117 | panic("fail") |
Luuk van Dijk | 25cf9bd | 2012-01-10 21:47:22 +0100 | [diff] [blame] | 118 | } |
Russ Cox | 1b31c37 | 2010-12-13 16:51:19 -0500 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | func ff(x int) { |
| 122 | call(func() { |
| 123 | _ = x |
| 124 | }) |
| 125 | } |
| 126 | |
| 127 | func call(func()) { |
Russ Cox | 0f4f2a6 | 2009-02-06 13:46:56 -0800 | [diff] [blame] | 128 | } |