Concurrent and Systems Programming: Cgrep Channels

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

Go

Concurrent and Systems Programming

cgrep
channels

04/25/10 cgrep – 1
04/25/10 cgrep – 2
cgrep/cgrep.go   Grep
package cgrep; import ( "bufio"; "io"; "os"; "regexp" )

func Grep(pat string, out, in chan *string, done chan<- os.Error) {


defer func() { out <- nil }() // upon return send nil to out

if pattern, ep := regexp.Compile(pat); ep != nil {


done <- ep; flush(in) // send error to done
} else {
for s := <-in; s != nil; s = <-in { // receive from in
if pattern.MatchString(*s) { out <- s } // send to out
}
done <- nil // send nil to done
}
}
func flush(in <-chan *string) { // read until nil
for <-in != nil { }
}

04/25/10 cgrep – 3
cgrep/cgrep.go   Source
func Source(out chan<- *string, r io.Reader, done chan<- os.Error) {
defer func() { out <- nil }() // upon return send nil to out
in := bufio.NewReader(r)
for {
switch body, er := in.ReadString('\n'); er {
case nil:
out <- &body
case os.EOF:
done <- nil
return
default:
done <- er
return
}
}
}

04/25/10 cgrep – 4
cgrep/cgrep.go   Sink
func Sink(out io.Writer, in <-chan *string, done chan<- os.Error) {
for body := <-in; body != nil; body = <-in {
if _, ew := io.WriteString(out, *body); ew != nil {
done <- ew
flush(in)
return
}
}
done <- nil
}

done accumulates results.


nil must be passed from Source to Sink to
ensure termination.

04/25/10 cgrep – 5
Channels
chan type // channel type
<- chan type // receive channel type (coerced)
chan <- type // send channel type

make(chan type) // construction; synchronous channel


make(chan type, capacity) // async bounded queue, default 0

<- channel // block until return received value


value, ok = <- channel // don’t block

channel <- value // block until send value


ok = channel <- value // don’t block (any test context)

close( channel ) // termination (written!)


closed( channel ) // detection (read!)

<- is left-associative for chan of chan.


close/closed is not too well defined, for
usage see cgrep2.

04/25/10 cgrep – 6

http://golang.org/doc/go_spec.html#Channel_types
http://golang.org/doc/go_spec.html#Communication_operators
http://www.cs.rit.edu/~ats/go-2009-3/code/cgrep2/
defer
defer function-call-expression

arguments are evaluated and saved.


function call is executed (LIFO) just before
the enclosing function returns.

04/25/10 cgrep – 7

http://golang.org/doc/go_spec.html#Defer_statements
cgrep/main.go   match
package main

import ( "flag"; "fmt"; "cgrep"; "os"; "runtime" )


func main() {
flag.Parse()
if flag.NArg() < 1 { // arguments?
fmt.Fprintln(os.Stderr, "usage: cgrep regular-expression ...")
os.Exit(1)
}
runtime.GOMAXPROCS(2) // arrange to schedule 2 CPUs
done := make(chan os.Error) // status reports
c := make(chan *string)
go cgrep.Source(c, os.Stdin, done) // stdin to first channel
for _, arg := range flag.Args() {
c1 := make(chan *string)
go cgrep.Grep(arg, c1, c, done) // one match per channel
c = c1
}

go cgrep.Sink(os.Stdout, c, done) // last channel to stdout


04/25/10 cgrep – 8
cgrep/main.go   status
ouch := 0 // count errors
for i := 0; i < flag.NArg()+2; i++ { // Source, 1/pattern, Sink
if e := <-done; e != nil {
fmt.Fprintf(os.Stderr, "cgrep: %s\n", e)
ouch++
}
}
os.Exit(ouch)
}

done channel can report each error of each


goroutine.

04/25/10 cgrep – 9
chan
$ chan

r a|b|s # receive on a specific channel


r * # receive on one of the three channels
r a|b|s ... # receive on each one of a set of channels
s a|b|s word # send a word on a specific channel
s a|b|s word ... # send words on a set of channels

chan allows experiments with channels:


synchronous, asynchronous, and buffered
make() make( ,1) make( ,3)

chan demonstrates various uses of channels,


make, and select.

04/25/10 cgrep – 10
select
select {
case channel <- value : statement; ...
case <- channel : statement; ...
case lvalue = <- channel : statement; ...
case lvalue := <- channel : statement; ...

default: statement; ...


}

select controls concurrent sending and


receiving on several channels.
select blocks unless there is a default.

04/25/10 cgrep – 11

http://golang.org/doc/go_spec.html#Select_statements

You might also like