Skip to content

Instantly share code, notes, and snippets.

@jszwedko
Created February 25, 2013 00:26
Show Gist options
  • Save jszwedko/5026451 to your computer and use it in GitHub Desktop.
Save jszwedko/5026451 to your computer and use it in GitHub Desktop.
Playing around with the ideas from Hoare's "A model for communicating sequential processes" (specifically section 10). Doesn't gracefully quit or do the print spooling thing. Run like: `go run multiprogrammed_batch_processing_system.go -readers 3 -printers 3 -processors 2 -job "3:3" -job "2" -job "1:1:1" -job "4:4:4:4:4:4" -job "5:5"`. See -h fo…
package main
import (
"flag"
"fmt"
"math/rand"
"strings"
"time"
)
const (
EOF = "-99"
)
var (
NumCardReaders int
NumLinePrinters int
NumProcessors int
UserJobs Jobs
)
func Process(in chan string) chan string {
output := make(chan string)
go func() {
for {
input := <-in
time.Sleep(time.Duration(rand.Intn(100) * 1000000)) //Do stuff
if input == EOF {
break
} else {
output <- input + "!"
}
}
close(output)
}()
return output
}
type Processor struct {
Id int
Readers chan *CardReader
Printers chan *LinePrinter
}
func NewProcessor(id int, cardReaders chan *CardReader, linePrinters chan *LinePrinter) *Processor {
me := &Processor{
Id: id,
Readers: cardReaders,
Printers: linePrinters,
}
go func() {
for {
var curCard string
var commandInput chan string
var commandOutput chan string
cardReader := <-me.Readers
linePrinter := <-me.Printers
curCard = <-cardReader.Output
if curCard == EOF {
cardReaders <- cardReader
linePrinters <- linePrinter
goto Cleanup //no work
}
commandInput = make(chan string)
commandOutput = Process(commandInput)
for {
select {
case output, ok := <-commandOutput:
if !ok {
cardReader.Finish <- true
goto Cleanup
}
linePrinter.Output <- fmt.Sprintf("P%d %s", me.Id, output)
case commandInput <- curCard:
curCard = <-cardReader.Output
}
}
Cleanup:
cardReaders <- cardReader
linePrinters <- linePrinter
}
}()
return me
}
type CardReader struct {
Id int
Cards chan string //This should really be a queue
Finish chan bool
Output chan string
}
func NewCardReader(id, buffer int) *CardReader {
me := &CardReader{
Id: id,
Cards: make(chan string, buffer),
Finish: make(chan bool),
Output: make(chan string),
}
go func() {
curCard, open := <-me.Cards
for {
if !open {
me.Output <- EOF
}
if curCard != EOF {
curCard = fmt.Sprintf("R%d %s", me.Id, curCard)
}
select {
case me.Output <- curCard:
if curCard != EOF {
curCard, open = <-me.Cards
}
case <-me.Finish:
curCard, open = <-me.Cards
}
}
}()
return me
}
type LinePrinter struct {
Id int
Output chan string
}
func NewLinePrinter(id int) *LinePrinter {
me := &LinePrinter{
Id: id,
Output: make(chan string),
}
go func() {
for {
fmt.Printf("L%d %s\n", me.Id, <-me.Output)
}
}()
return me
}
type Job struct {
Cards []string
}
type Jobs []*Job
func (me *Jobs) String() string {
return ""
}
func (me *Jobs) Set(value string) error {
parts := strings.Split(value, ":")
job := &Job{
Cards: parts,
}
*me = append(*me, job)
return nil
}
func init() {
flag.IntVar(&NumCardReaders, "readers", 1, "Number of card readers")
flag.IntVar(&NumLinePrinters, "printers", 1, "Number of line printers")
flag.IntVar(&NumProcessors, "processors", 1, "Number of processors")
flag.Var(&UserJobs, "job", "Job specified as list of : seperated values (don't use -99 ;) )")
flag.Parse()
}
func main() {
cardReaders := make(chan *CardReader, NumCardReaders)
linePrinters := make(chan *LinePrinter, NumLinePrinters)
processors := make([]*Processor, NumProcessors)
quit := make(chan int)
for i := 0; i < NumCardReaders; i++ {
cardReaders <- NewCardReader(i, 10000)
}
//Place cards in card reader
for _, job := range UserJobs {
cardReader := <-cardReaders
for _, card := range job.Cards {
cardReader.Cards <- card
}
cardReader.Cards <- EOF
cardReaders <- cardReader
}
//Close card reader queues
for i := 0; i < NumCardReaders; i++ {
cardReader := <-cardReaders
close(cardReader.Cards)
cardReaders <- cardReader
}
for i := 0; i < cap(linePrinters); i++ {
linePrinters <- NewLinePrinter(i)
}
for i := 0; i < len(processors); i++ {
processors[i] = NewProcessor(i, cardReaders, linePrinters)
}
<-quit
}
@meatballhat
Copy link

It's a dumb little detail, but now that this has broken out of the playground it could likely use a rand.Seed(...) :trollface:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment