github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/channel.go (about)

     1  package main
     2  
     3  import (
     4  	"runtime"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  var wg sync.WaitGroup
    10  
    11  type intchan chan int
    12  
    13  func main() {
    14  	ch := make(chan int, 2)
    15  	ch <- 1
    16  	println("len, cap of channel:", len(ch), cap(ch), ch == nil)
    17  
    18  	ch = make(chan int)
    19  	println("len, cap of channel:", len(ch), cap(ch), ch == nil)
    20  
    21  	wg.Add(1)
    22  	go sender(ch)
    23  
    24  	n, ok := <-ch
    25  	println("recv from open channel:", n, ok)
    26  
    27  	for n := range ch {
    28  		println("received num:", n)
    29  	}
    30  
    31  	wg.Wait()
    32  	n, ok = <-ch
    33  	println("recv from closed channel:", n, ok)
    34  
    35  	// Test various channel size types.
    36  	_ = make(chan int, int8(2))
    37  	_ = make(chan int, int16(2))
    38  	_ = make(chan int, int32(2))
    39  	_ = make(chan int, int64(2))
    40  	_ = make(chan int, uint8(2))
    41  	_ = make(chan int, uint16(2))
    42  	_ = make(chan int, uint32(2))
    43  	_ = make(chan int, uint64(2))
    44  
    45  	// Test that named channels don't crash the compiler.
    46  	named := make(intchan, 1)
    47  	named <- 3
    48  	<-named
    49  	select {
    50  	case <-named:
    51  	default:
    52  	}
    53  
    54  	// Test bigger values
    55  	ch2 := make(chan complex128)
    56  	wg.Add(1)
    57  	go sendComplex(ch2)
    58  	println("complex128:", <-ch2)
    59  	wg.Wait()
    60  
    61  	// Test multi-sender.
    62  	ch = make(chan int)
    63  	wg.Add(3)
    64  	go fastsender(ch, 10)
    65  	go fastsender(ch, 23)
    66  	go fastsender(ch, 40)
    67  	slowreceiver(ch)
    68  	wg.Wait()
    69  
    70  	// Test multi-receiver.
    71  	ch = make(chan int)
    72  	wg.Add(3)
    73  	go fastreceiver(ch)
    74  	go fastreceiver(ch)
    75  	go fastreceiver(ch)
    76  	slowsender(ch)
    77  	wg.Wait()
    78  
    79  	// Test iterator style channel.
    80  	ch = make(chan int)
    81  	wg.Add(1)
    82  	go iterator(ch, 100)
    83  	sum := 0
    84  	for i := range ch {
    85  		sum += i
    86  	}
    87  	wg.Wait()
    88  	println("sum(100):", sum)
    89  
    90  	// Test simple selects.
    91  	go selectDeadlock() // cannot use waitGroup here - never terminates
    92  	wg.Add(1)
    93  	go selectNoOp()
    94  	wg.Wait()
    95  
    96  	// Test select with a single send operation (transformed into chan send).
    97  	ch = make(chan int)
    98  	wg.Add(1)
    99  	go fastreceiver(ch)
   100  	select {
   101  	case ch <- 5:
   102  	}
   103  	close(ch)
   104  	wg.Wait()
   105  	println("did send one")
   106  
   107  	// Test select with a single recv operation (transformed into chan recv).
   108  	select {
   109  	case n := <-ch:
   110  		println("select one n:", n)
   111  	}
   112  
   113  	// Test select recv with channel that has one entry.
   114  	ch = make(chan int)
   115  	wg.Add(1)
   116  	go func(ch chan int) {
   117  		runtime.Gosched()
   118  		ch <- 55
   119  		wg.Done()
   120  	}(ch)
   121  	select {
   122  	case make(chan int) <- 3:
   123  		println("unreachable")
   124  	case <-(chan int)(nil):
   125  		println("unreachable")
   126  	case n := <-ch:
   127  		println("select n from chan:", n)
   128  	case n := <-make(chan int):
   129  		println("unreachable:", n)
   130  	}
   131  	wg.Wait()
   132  
   133  	// Test select recv with closed channel.
   134  	close(ch)
   135  	select {
   136  	case make(chan int) <- 3:
   137  		println("unreachable")
   138  	case n := <-ch:
   139  		println("select n from closed chan:", n)
   140  	case n := <-make(chan int):
   141  		println("unreachable:", n)
   142  	}
   143  
   144  	// Test select send.
   145  	ch = make(chan int)
   146  	wg.Add(1)
   147  	go fastreceiver(ch)
   148  	select {
   149  	case ch <- 235:
   150  		println("select send")
   151  	case n := <-make(chan int):
   152  		println("unreachable:", n)
   153  	}
   154  	close(ch)
   155  	wg.Wait()
   156  
   157  	// test non-concurrent buffered channels
   158  	ch = make(chan int, 2)
   159  	ch <- 1
   160  	ch <- 2
   161  	println("non-concurrent channel receive:", <-ch)
   162  	println("non-concurrent channel receive:", <-ch)
   163  
   164  	// test closing channels with buffered data
   165  	ch <- 3
   166  	ch <- 4
   167  	close(ch)
   168  	println("closed buffered channel receive:", <-ch)
   169  	println("closed buffered channel receive:", <-ch)
   170  	println("closed buffered channel receive:", <-ch)
   171  
   172  	// test using buffered channels as regular channels with special properties
   173  	wg.Add(6)
   174  	ch = make(chan int, 2)
   175  	go send(ch)
   176  	go send(ch)
   177  	go send(ch)
   178  	go send(ch)
   179  	go receive(ch)
   180  	go receive(ch)
   181  	wg.Wait()
   182  	close(ch)
   183  	var count int
   184  	for range ch {
   185  		count++
   186  	}
   187  	println("hybrid buffered channel receive:", count)
   188  
   189  	// test blocking selects
   190  	ch = make(chan int)
   191  	sch1 := make(chan int)
   192  	sch2 := make(chan int)
   193  	sch3 := make(chan int)
   194  	wg.Add(3)
   195  	go func() {
   196  		defer wg.Done()
   197  		time.Sleep(time.Millisecond)
   198  		sch1 <- 1
   199  	}()
   200  	go func() {
   201  		defer wg.Done()
   202  		time.Sleep(time.Millisecond)
   203  		sch2 <- 2
   204  	}()
   205  	go func() {
   206  		defer wg.Done()
   207  		// merge sch2 and sch3 into ch
   208  		for i := 0; i < 2; i++ {
   209  			var v int
   210  			select {
   211  			case v = <-sch1:
   212  			case v = <-sch2:
   213  			}
   214  			select {
   215  			case sch3 <- v:
   216  				panic("sent to unused channel")
   217  			case ch <- v:
   218  			}
   219  		}
   220  	}()
   221  	sum = 0
   222  	for i := 0; i < 2; i++ {
   223  		select {
   224  		case sch3 <- sum:
   225  			panic("sent to unused channel")
   226  		case v := <-ch:
   227  			sum += v
   228  		}
   229  	}
   230  	wg.Wait()
   231  	println("blocking select sum:", sum)
   232  }
   233  
   234  func send(ch chan<- int) {
   235  	ch <- 1
   236  	wg.Done()
   237  }
   238  
   239  func receive(ch <-chan int) {
   240  	<-ch
   241  	wg.Done()
   242  }
   243  
   244  func sender(ch chan int) {
   245  	for i := 1; i <= 8; i++ {
   246  		if i == 4 {
   247  			time.Sleep(time.Microsecond)
   248  			println("slept")
   249  		}
   250  		ch <- i
   251  	}
   252  	close(ch)
   253  	wg.Done()
   254  }
   255  
   256  func sendComplex(ch chan complex128) {
   257  	ch <- 7 + 10.5i
   258  	wg.Done()
   259  }
   260  
   261  func fastsender(ch chan int, n int) {
   262  	ch <- n
   263  	ch <- n + 1
   264  	wg.Done()
   265  }
   266  
   267  func slowreceiver(ch chan int) {
   268  	sum := 0
   269  	for i := 0; i < 6; i++ {
   270  		sum += <-ch
   271  		time.Sleep(time.Microsecond)
   272  	}
   273  	println("sum of n:", sum)
   274  }
   275  
   276  func slowsender(ch chan int) {
   277  	for n := 0; n < 6; n++ {
   278  		time.Sleep(time.Microsecond)
   279  		ch <- 12 + n
   280  	}
   281  }
   282  
   283  func fastreceiver(ch chan int) {
   284  	sum := 0
   285  	for i := 0; i < 2; i++ {
   286  		n := <-ch
   287  		sum += n
   288  	}
   289  	println("sum:", sum)
   290  	wg.Done()
   291  }
   292  
   293  func iterator(ch chan int, top int) {
   294  	for i := 0; i < top; i++ {
   295  		ch <- i
   296  	}
   297  	close(ch)
   298  	wg.Done()
   299  }
   300  
   301  func selectDeadlock() {
   302  	println("deadlocking")
   303  	select {}
   304  	println("unreachable")
   305  }
   306  
   307  func selectNoOp() {
   308  	println("select no-op")
   309  	select {
   310  	default:
   311  	}
   312  	println("after no-op")
   313  	wg.Done()
   314  }