| 1 | package main
 | 
|---|
| 2 | 
 | 
|---|
| 3 | import (
 | 
|---|
| 4 |         "fmt"
 | 
|---|
| 5 |         "sync"
 | 
|---|
| 6 |         "time"
 | 
|---|
| 7 |         "runtime"
 | 
|---|
| 8 |         "os"
 | 
|---|
| 9 |         "strconv"
 | 
|---|
| 10 | )
 | 
|---|
| 11 | 
 | 
|---|
| 12 | var Processors, Channels, Prods, Cons, ChannelSize int = 2, 2, 1, 1, 10
 | 
|---|
| 13 | var cons_done, prod_done bool = false, false;
 | 
|---|
| 14 | var total_operations, cons_check, prod_check uint64 = 0, 0, 0
 | 
|---|
| 15 | var m sync.Mutex
 | 
|---|
| 16 | 
 | 
|---|
| 17 | var prodJoin chan int = make(chan int, Prods)
 | 
|---|
| 18 | var consJoin chan int = make(chan int, Cons)
 | 
|---|
| 19 | 
 | 
|---|
| 20 | func consumer( chans [] chan uint64 ) {
 | 
|---|
| 21 |         var count uint64 = 0
 | 
|---|
| 22 |         for {
 | 
|---|
| 23 |                 if cons_done { break }
 | 
|---|
| 24 |                 
 | 
|---|
| 25 |                 select {
 | 
|---|
| 26 |                         case <- chans[0]:
 | 
|---|
| 27 |                         case <- chans[1]:
 | 
|---|
| 28 |                 }
 | 
|---|
| 29 |                 if ! prod_done { count++ }
 | 
|---|
| 30 |         }
 | 
|---|
| 31 |         m.Lock()
 | 
|---|
| 32 |         total_operations += count
 | 
|---|
| 33 |         m.Unlock()
 | 
|---|
| 34 |         consJoin <- 0
 | 
|---|
| 35 | }
 | 
|---|
| 36 | 
 | 
|---|
| 37 | func producer( chans [] chan uint64 ) {
 | 
|---|
| 38 |         var count uint64 = 0
 | 
|---|
| 39 |         for {
 | 
|---|
| 40 |                 if prod_done { break }
 | 
|---|
| 41 |                 select {
 | 
|---|
| 42 |                         case chans[0] <- count:
 | 
|---|
| 43 |                         case chans[1] <- count:
 | 
|---|
| 44 |                 }
 | 
|---|
| 45 |                 count++
 | 
|---|
| 46 |         }
 | 
|---|
| 47 |         prodJoin <- 0
 | 
|---|
| 48 | }
 | 
|---|
| 49 | 
 | 
|---|
| 50 | func usage() {
 | 
|---|
| 51 |         fmt.Printf( "Usage: %v " +
 | 
|---|
| 52 |                 "[ processors (> 0) | 'd' (default %v) ] " +
 | 
|---|
| 53 |                 "[ ChannelSize (> 0) | 'd' (default %v) ]\n",
 | 
|---|
| 54 |                 os.Args[0], Processors, ChannelSize );
 | 
|---|
| 55 |         os.Exit( 1 );
 | 
|---|
| 56 | }
 | 
|---|
| 57 | 
 | 
|---|
| 58 | func main() {
 | 
|---|
| 59 |         switch len( os.Args ) {
 | 
|---|
| 60 |                 case 3:
 | 
|---|
| 61 |                         if os.Args[2] != "d" {                                                  // default ?
 | 
|---|
| 62 |                                 ChannelSize, _ = strconv.Atoi( os.Args[2] )
 | 
|---|
| 63 |                                         if ChannelSize < 0 { usage(); }
 | 
|---|
| 64 |                         } // if
 | 
|---|
| 65 |                 fallthrough
 | 
|---|
| 66 |                 case 2:
 | 
|---|
| 67 |                         if os.Args[1] != "d" {                                                  // default ?
 | 
|---|
| 68 |                                 Processors, _ = strconv.Atoi( os.Args[1] )
 | 
|---|
| 69 |                                 if Processors < 1 { usage(); }
 | 
|---|
| 70 |                         } // if
 | 
|---|
| 71 |                 case 1:                                                                                 // use defaults
 | 
|---|
| 72 |                 default:
 | 
|---|
| 73 |                 usage();
 | 
|---|
| 74 |         } // switch
 | 
|---|
| 75 |         runtime.GOMAXPROCS( Processors );
 | 
|---|
| 76 |         Prods = Processors /2
 | 
|---|
| 77 |         Cons = Processors / 2
 | 
|---|
| 78 | 
 | 
|---|
| 79 |         // fmt.Println("Processors: ",Processors," Channels: ",Channels," ProdsPerChan: ",ProdsPerChan," ConsPerChan: ",ConsPerChan," Channel Size: ",ChannelSize)
 | 
|---|
| 80 |         
 | 
|---|
| 81 |         chans := make( [] chan uint64, Channels )
 | 
|---|
| 82 |         for i := range chans {
 | 
|---|
| 83 |                 chans[i] = make(chan uint64, ChannelSize)
 | 
|---|
| 84 |         }
 | 
|---|
| 85 |         for j := 0; j < Prods; j++ {
 | 
|---|
| 86 |                 go producer( chans )
 | 
|---|
| 87 |         }
 | 
|---|
| 88 | 
 | 
|---|
| 89 |         for j := 0; j < Cons; j++ {
 | 
|---|
| 90 |                 go consumer( chans )
 | 
|---|
| 91 |         }
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         // wait 10 seconds
 | 
|---|
| 94 |         time.Sleep(time.Second * 10)
 | 
|---|
| 95 |         // fmt.Println("prod done\n")
 | 
|---|
| 96 |         prod_done = true
 | 
|---|
| 97 |         for j := 0; j < Prods; j++ {
 | 
|---|
| 98 |                 <-prodJoin
 | 
|---|
| 99 |         }
 | 
|---|
| 100 |         // fmt.Println("cons done\n")
 | 
|---|
| 101 |         cons_done = true
 | 
|---|
| 102 |         for i := range chans {
 | 
|---|
| 103 |                 close(chans[i])
 | 
|---|
| 104 |         }
 | 
|---|
| 105 |         
 | 
|---|
| 106 |         for j := 0; j < Cons; j++{
 | 
|---|
| 107 |                 <-consJoin
 | 
|---|
| 108 |         }
 | 
|---|
| 109 | 
 | 
|---|
| 110 |     fmt.Println(total_operations)
 | 
|---|
| 111 | }
 | 
|---|