Skip to content

Instantly share code, notes, and snippets.

@jmingov
Created June 10, 2018 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jmingov/40a7dadea45efb5341416fe481dcc2df to your computer and use it in GitHub Desktop.
Save jmingov/40a7dadea45efb5341416fe481dcc2df to your computer and use it in GitHub Desktop.
package main
import (
"log"
"math/rand"
"time"
)
type Threader struct {
TIME_LIMIT time.Time
numWorkers int
jobs int
jobsProduced int
doneProducing chan bool
doneReceiving chan bool
pwChan chan int
wrChan chan int
errChan chan error
initTime time.Time
}
const TIME_LIMIT = time.Second
func main() {
mimt := Threader{}
mimt.Init(4, 8)
}
func (tr Threader) Init(numWorkers int, jobs int) {
tr.doneProducing = make(chan bool)
tr.doneReceiving = make(chan bool)
tr.pwChan = make(chan int)
tr.wrChan = make(chan int)
tr.errChan = make(chan error)
tr.initTime = time.Now()
tr.numWorkers = numWorkers
tr.jobs = jobs
// start producing jobs
go tr.produce()
// start waiting for jobs done
go tr.receiver()
// start workers for jobs
for i := 0; i < tr.numWorkers; i++ {
go tr.work()
}
// wait for done producing
<-tr.doneProducing
}
func (tr Threader) produce() {
// current job
i := 0
// marker for timing
tr.jobsProduced = 0
// start tracking time passed producing
t := time.Now()
for {
// we have sent 1 job per worker, trap till tl has passed
if tr.jobsProduced == tr.numWorkers {
// if moreThanTimeLimit has passed
if moreThanTL(t) {
// reset
tr.jobsProduced = 0
t = time.Now()
}
} else {
// normal round, send work
log.Printf("Sending %d", i)
// send job
tr.pwChan <- i
// add to counters
i += 1
tr.jobsProduced += 1
}
// we finished doing our jobs, quit producing
if i == tr.jobs {
//log.Printf("Rondas done %d", i)
break
}
}
end(tr.initTime, "PRODUCE")
// make main wait for all to finish
tr.doneProducing <- <-tr.doneReceiving
}
func (tr Threader) work() {
// the routine receives the data,
// sleeps for a random time
// and sends response to receiver (wrChan)
for {
resp := <-tr.pwChan
// do work
myrand := time.Duration(random(0, 100))
time.Sleep(myrand * (time.Second / 100))
// rend response
tr.wrChan <- resp
}
}
func (tr Threader) receiver() {
// waits for msgs from workers
for {
u := <-tr.wrChan
log.Printf("Received %d", u)
// all workers finished, quit
if u == (tr.jobs - 1) {
break
}
}
end(tr.initTime, "RECEIVE")
tr.doneReceiving <- true
}
////
// helpers
////
func moreThanTL(t time.Time) bool {
elapsed := time.Since(t)
if TIME_LIMIT < elapsed {
return true
}
return false
}
func end(t time.Time, s string) {
elapsed := time.Since(t)
log.Printf("%s took %s", s, elapsed)
}
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max-min) + min
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment