Advertisement
Guest User

gol.go

a guest
Dec 7th, 2019
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 5.41 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "fmt"
  5.     "strconv"
  6.     "strings"
  7.     "time"
  8. )
  9.  
  10. func sendWorld(p golParams, world [][]byte, d distributorChans, turn int) {
  11.     d.io.command <- ioOutput
  12.     d.io.filename <- strings.Join([]string{strconv.Itoa(p.imageWidth), strconv.Itoa(p.imageHeight), "Turn:" + strconv.Itoa(turn)}, "x")
  13.  
  14.     for y := range world {
  15.         for x := range world[y] {
  16.             d.io.outputVal <- world[y][x]
  17.         }
  18.     }
  19. }
  20.  
  21. func printAliveCells(p golParams, world [][]byte) {
  22.     alive := 0
  23.     for y := 0; y < p.imageHeight; y++ {
  24.         for x := 0; x < p.imageWidth; x++ {
  25.             if world[y][x] == 0xFF {
  26.                 alive ++
  27.             }
  28.         }
  29.     }
  30.     fmt.Println("Number of Alive Cells:", alive)
  31. }
  32.  
  33. func isAlive(imageWidth, x, y int, world [][]byte) bool {
  34.     x += imageWidth
  35.     x %= imageWidth
  36.     if world[y][x] == 0 {
  37.         return false
  38.     } else {
  39.         return true
  40.  
  41.     }
  42. }
  43.  
  44. func worker(haloHeight int, in <-chan byte, out chan<- byte, p golParams) {
  45.     workerWorld := make([][]byte, haloHeight)
  46.     for i := range workerWorld {
  47.         workerWorld[i] = make([]byte, p.imageWidth)
  48.     }
  49.     for {
  50.         for y := 0; y < haloHeight; y++ {
  51.             for x := 0; x < p.imageWidth; x++ {
  52.                 workerWorld[y][x] = <-in
  53.             }
  54.         }
  55.  
  56.         for y := 1; y < haloHeight-1; y++ {
  57.             for x := 0; x < p.imageWidth; x++ {
  58.                 count := 0
  59.                 for i := -1; i <= 1; i++ {
  60.                     for j := -1; j <= 1; j++ {
  61.                         if (j != 0 || i != 0) && isAlive(p.imageWidth, x+i, y+j, workerWorld) {
  62.                             count++
  63.                         }
  64.                     }
  65.                 }
  66.                 if count == 3 || (isAlive(p.imageWidth, x, y, workerWorld) && count == 2) {
  67.                     out <- 0xFF
  68.                 } else {
  69.                     out <- 0
  70.                 }
  71.             }
  72.         }
  73.     }
  74. }
  75. /**
  76. Stage 4 Idea:
  77. - https://tcpp.cs.gsu.edu/curriculum/?q=system/files/ch10.pdf
  78. - Each thread manages two halo's/row's
  79.     - each thread must receive from two other threads/halos each turn.
  80.         - Turn Start:
  81.             - each thread sends out its halo
  82.             - each thread receives from two other threads
  83.         - Turn End:
  84.             - each thread processes it's own world and changes it's halo
  85. - Have a 'DoneManager' that checks all threads are done working on the current turn->once buffer fills-> send signal to
  86. threads to process next turn.
  87. - Have a 'Turn Manager' that has a buffer of size turns-> as soon as this is full all turns are over and get distributor to
  88. receive world from all threads.
  89. - Making sure inputs work i.e. have multiple input channels that pause all workers
  90. **/
  91.  
  92. // distributor divides the work between workers and interacts with other goroutines.
  93. func distributor(p golParams, d distributorChans, alive chan []cell, in []chan byte, out []chan byte) {
  94.  
  95.     // Create the 2D slice to store the world.
  96.     world := make([][]byte, p.imageHeight)
  97.     for i := range world {
  98.         world[i] = make([]byte, p.imageWidth)
  99.     }
  100.  
  101.     // Request the io goroutine to read in the image with the given filename.
  102.     d.io.command <- ioInput
  103.     d.io.filename <- strings.Join([]string{strconv.Itoa(p.imageWidth), strconv.Itoa(p.imageHeight)}, "x")
  104.  
  105.     // The io goroutine sends the requested image byte by byte, in rows.
  106.     for y := 0; y < p.imageHeight; y++ {
  107.         for x := 0; x < p.imageWidth; x++ {
  108.             val := <-d.io.inputVal
  109.             if val != 0 {
  110.                 world[y][x] = val
  111.             }
  112.         }
  113.     }
  114.     threadHeight := p.imageHeight / p.threads
  115.     extra := p.imageHeight % p.threads
  116.     fmt.Println(strconv.Itoa(extra))
  117.     ticker := time.NewTicker(2 * time.Second)
  118.  
  119. loop1:
  120.     for turn := 0; turn < p.turns; turn++ {
  121.         select {
  122.         case keyValue := <-d.key:
  123.             char := string(keyValue)
  124.             if char == "s" {
  125.                 fmt.Println("S Pressed")
  126.                 go sendWorld(p, world, d, turn)
  127.                 printAliveCells(p, world)
  128.             }
  129.             if char == "q" {
  130.                 fmt.Println("Q pressed, breaking from loop")
  131.                 break loop1
  132.             }
  133.             if char == "p" {
  134.                 fmt.Println("P pressed, pausing at turn" + strconv.Itoa(turn))
  135.                 //ticker.Stop()
  136.             loop:
  137.                 for {
  138.                     select {
  139.                     case keyValue := <-d.key:
  140.                         char := string(keyValue)
  141.                         if char == "p" {
  142.                             fmt.Println("Continuing")
  143.                             //ticker = time.NewTicker(2 * time.Second)
  144.                             break loop
  145.                         }
  146.                     default:
  147.                     }
  148.                 }
  149.             }
  150.         case <-ticker.C:
  151.             go printAliveCells(p, world)
  152.  
  153.         default:
  154.             for i := 0; i < p.threads; i++ {
  155.                 yBound := threadHeight + 2
  156.                 if i == p.threads-1 && !powerOfTwo(p) {
  157.                     yBound += extra
  158.                 }
  159.                 for y := 0; y < yBound; y++ {
  160.                     proposedY := y + (i * threadHeight) - 1
  161.                     if proposedY < 0 {
  162.                         proposedY += p.imageHeight
  163.                     }
  164.                     proposedY %= p.imageHeight
  165.                     for x := 0; x < p.imageWidth; x++ {
  166.                         in[i] <- world[proposedY][x]
  167.                     }
  168.                 }
  169.             }
  170.             for i := 0; i < p.threads; i++ {
  171.                 for y := 0; y < threadHeight; y++ {
  172.                     for x := 0; x < p.imageWidth; x++ {
  173.                         world[y+(i*(threadHeight))][x] = <-out[i]
  174.                     }
  175.                 }
  176.             }
  177.             if !powerOfTwo(p) {
  178.                 for e := 0; e < extra; e++ {
  179.                     for x := 0; x < p.imageWidth; x++ {
  180.                         world[e+(p.threads*(threadHeight))][x] = <-out[p.threads-1]
  181.                     }
  182.                 }
  183.             }
  184.         }
  185.     }
  186.     sendWorld(p, world, d, p.turns)
  187.  
  188.     // Create an empty slice to store coordinates of cells that are still alive after p.turns are done.
  189.     var finalAlive []cell
  190.     // Go through the world and append the cells that are still alive.
  191.     for y := 0; y < p.imageHeight; y++ {
  192.         for x := 0; x < p.imageWidth; x++ {
  193.             if world[y][x] != 0 {
  194.                 finalAlive = append(finalAlive, cell{x: x, y: y})
  195.             }
  196.         }
  197.     }
  198.  
  199.     // Make sure that the Io has finished any output before exiting.
  200.     d.io.command <- ioCheckIdle
  201.     <-d.io.idle
  202.  
  203.     // Return the coordinates of cells that are still alive.
  204.     alive <- finalAlive
  205. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement