Adding some erlang stuff.
This commit is contained in:
parent
4aae9be7cd
commit
71975c1070
44
pe/ring.erl
44
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.
|
||||
|
|
51
pe/ring.go
51
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue