Skip to content

Instantly share code, notes, and snippets.

@husobee
Created February 6, 2018 12:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save husobee/c4fe849b4435946281b9909eea1191e7 to your computer and use it in GitHub Desktop.
Save husobee/c4fe849b4435946281b9909eea1191e7 to your computer and use it in GitHub Desktop.
producer-consumer problem with message passing
package main
import (
"errors"
"fmt"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type Result struct {
s string
err error
}
type Message struct {
input string
resultChan chan Result
}
type Queue struct {
q [32]string
i int
popChan chan Message
pushChan chan Message
}
func (q *Queue) Push(s string) error {
resultChan := make(chan Result)
q.pushChan <- Message{
input: s,
resultChan: resultChan}
result := <-resultChan
return result.err
}
func (q *Queue) Pop() (string, error) {
resultChan := make(chan Result)
q.popChan <- Message{
resultChan: resultChan}
result := <-resultChan
return result.s, result.err
}
func (q *Queue) Controller() {
q.popChan = make(chan Message)
q.pushChan = make(chan Message)
for {
select {
case message := <-q.pushChan:
err := q.push(message.input)
message.resultChan <- Result{err: err}
case message := <-q.popChan:
s, err := q.pop()
message.resultChan <- Result{
s: s,
err: err}
}
}
}
func (q *Queue) push(s string) error {
if q.i == 31 {
return errors.New("Full")
}
q.i++
q.q[q.i] = s
return nil
}
func (q *Queue) pop() (string, error) {
if q.i == 0 {
return "", errors.New("Full")
}
q.i--
return q.q[q.i], nil
}
func (q *Queue) Len() int {
return q.i
}
func main() {
var queue = new(Queue)
go queue.Controller()
go consumer(queue)
producer(queue)
}
func consumer(queue *Queue) {
for {
l := queue.Len()
for i := 0; i < l; i++ {
s, err := queue.Pop()
fmt.Printf("read: %s, %v\n", s, err)
if err != nil {
time.Sleep(1 * time.Second)
break
}
}
}
}
func producer(queue *Queue) {
for {
l := queue.Len()
for i := l; i < 32; i++ {
s := randomString()
err := queue.Push(s)
fmt.Printf("wrote: %s, %v\n", s, err)
if err != nil {
time.Sleep(1 * time.Second)
break
}
}
}
}
func randomString() string {
w := make([]byte, 5)
rand.Read(w)
return fmt.Sprintf("%X", w)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment