diff --git a/pe/ring.erl b/pe/ring.erl index 78d2547..4871f25 100644 --- a/pe/ring.erl +++ b/pe/ring.erl @@ -5,3 +5,47 @@ %% Write a similar program in some other programming language you are %% familiar with. Compare the results. Write a blog, and publish the %% results on the internet! +-module(ring). +-compile(export_all). % TODO: remove this +-record(message, {client=undefined, ttl=0, hops=0}). + +%% What does a loop need to know? Who to forward to next. +%% +%% How does the last node know who to forward to? We need to pass the +%% parent in somehow. +%% +loop(Next) -> + receive + #message{client=Client, ttl=TTL, hops=Hops} -> + if TTL > 0 -> + Next ! #message{client=Client, ttl=TTL-1, hops=Hops}; + true -> + Client ! #message{client=Client, ttl=TTL, hops=Hops} + end + end. + + +%% gen_process -> +%% 1. is N > 0? +%% 1. Spawn process, use self() as next. +%% This generates processes in the reverse order, e.g. +%% this process is the last process in the chain. + +gen_process(N) when is_number(N) -> + Root = self(), + Child = gen_process(Root, Root, N-1), + loop(Child). + +gen_process(Root, _Parent, 0) -> + loop(Root); + +gen_process(Root, Parent, Count) when Count > 0 -> + Child = gen_process(Root, Parent, Count-1), + loop(Child). + +ring(N) -> + Root = spawn(fun () -> gen_process(N) end), + Root ! #message{client=self(), ttl=N, hops=0}, + receive X -> + X + end. diff --git a/pe/ring.go b/pe/ring.go index 51d232c..f065681 100644 --- a/pe/ring.go +++ b/pe/ring.go @@ -1,6 +1,53 @@ package main +import ( + "fmt" + "time" +) + type Message struct { - RCount int // how many times around the ring have we been - FCount int // how many times has the message been forwarded + TTL int + Parent chan Message +} + +func process(from, next chan Message, id int) { + fmt.Printf("PID %d: from=%p, next=%p\n", id, from, next) + for { + message, ok := <-from + if !ok { + return + } + + fmt.Printf("process %d: message: %+v\n", message) + message.TTL-- + if message.TTL == 0 { + message.Parent <- message + } + + next <- message + } +} + +func genProcess(count int) chan Message { + fmt.Printf("spawn: %p, count=%d\n", from, count) + next := make(chan Message, 0) + count-- + go process(from, next, count) + if count == 0 { + return from + } + + return genProcess(next, count) +} + +func main() { + fmt.Println("startup") + entrypoint := make(chan Message, 0) + ring := genProcess(entrypoint, 3) + fmt.Printf("%p\t%p\n", ring, entrypoint) + time.Sleep(1) + rcv := make(chan Message, 0) + message := Message{3, rcv} + message = <-rcv + fmt.Println(message) }