Last active
January 3, 2016 07:49
-
-
Save hfeeki/8432017 to your computer and use it in GitHub Desktop.
Process ring.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% from https://erlangcentral.org/wiki/index.php/Process_Ring_Across_Nodes | |
%% | |
%% Written by Mazen Harake | |
%% GPLv3 License -> http://www.gnu.org/licenses/gpl-3.0.txt | |
-module(nodeloop). | |
-compile(export_all). | |
start(N) when N > 0 -> | |
erlang:register(head, proc_lib:spawn_link(?MODULE, head_proc, [nil, nil])), | |
create_links(N). | |
create_links(0) -> | |
ok; | |
create_links(N) when N > 0 -> | |
head ! {cmd, spawn_new}, | |
create_links(N - 1). | |
stop() -> | |
head ! {cmd, stop}. | |
send(Msg, NodeSkips) when NodeSkips > 0 -> | |
head ! {msg, node(), NodeSkips, 0, 1, Msg}. | |
head_proc(nil, Next) -> | |
receive | |
{msg, Origin, MaxNodeSkips, NodeSkips, ProcSkips, Msg} -> | |
case {node(), MaxNodeSkips == NodeSkips} of | |
{Origin, true} -> | |
io:format("head: Finished!~n"); | |
{Origin, false} -> | |
Next ! {msg, Origin, MaxNodeSkips, NodeSkips+1, ProcSkips, Msg}; | |
{_, _} -> | |
Next ! {msg, Origin, MaxNodeSkips, NodeSkips, ProcSkips, Msg} | |
end, | |
?MODULE:head_proc(nil,Next); | |
{cmd, stop} -> | |
Next ! {cmd, stop}, | |
io:format("head: Stop sent, Exiting...!~n"); | |
{cmd, spawn_new} -> | |
Pid = proc_lib:spawn_link(?MODULE, link_proc, [nil, nil]), | |
Pid ! {cmd, linkin, [head, Next]}, | |
io:format("head: Added ~p...~n",[Pid]), | |
?MODULE:head_proc(nil, Pid) | |
end. | |
link_proc(Prev, Next) -> | |
receive | |
{cmd, linkin, [NewPrev, NewNext]} -> | |
?MODULE:link_proc(NewPrev, NewNext); | |
{msg, Origin, MaxNodeSkips, NodeSkips, ProcSkips, Msg} -> | |
io:format("~p: ~p | ~p | ~p | ~p | ~1000p~n", | |
[self(), Origin, MaxNodeSkips, NodeSkips, ProcSkips, Msg]), | |
timer:sleep(50), | |
Receiver = next(Next), | |
Receiver ! {msg, Origin, MaxNodeSkips, NodeSkips, ProcSkips + 1, Msg}, | |
?MODULE:link_proc(Prev, Next); | |
{cmd, stop} -> | |
io:format("~p: Exiting...~n",[self()]), | |
next(Next) ! {cmd, stop} | |
end. | |
next(nil) -> | |
Nodes = lists:sort([node()|nodes()]), | |
{head, nextnode(hd(Nodes), node(), Nodes)}; | |
next(Pid) -> Pid. | |
nextnode(First, _Me, []) -> First; | |
nextnode(_First, Me, [Me, Next | _Rest]) -> Next; | |
nextnode(First, Me, [_|Rest]) -> nextnode(First, Me, Rest). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% | |
%% from: http://stackoverflow.com/questions/16438367/erlang-ring-controller-process-related | |
%% | |
%% The first one is: The control spawns all the workers in the ring and here is the solution: | |
%% | |
-module(ring). | |
-export([start/3, create/4]). | |
start(M, N, Message) -> | |
create(undef, N, M, Message). | |
create(Parent, 0, M, Message) -> | |
Parent ! {created, self()}, | |
evaluate(Parent, M, Message); | |
create(Parent, N, M, Message) -> | |
Child = spawn(?MODULE, create, [self(), N-1, M, Message]), | |
io:format("~w ~w created~n", [Child, N]), | |
evaluate(Parent, M, Message). | |
evaluate(undef, M, Message) -> | |
receive | |
{created, Last} -> | |
Last ! Message, | |
io:format("~w sent ~w to ~w~n", [self(), Message, Last]), | |
evaluate(Last, M-1, Message) | |
end; | |
evaluate(Parent, 0, _) -> | |
receive | |
Msg -> | |
io:format("~w received ~w~n", [self(), Msg]), | |
Parent ! stop, | |
io:format("~w sent ~w to ~w~n", [self(), stop, Parent]) | |
end; | |
evaluate(Parent, M, Message) -> | |
receive | |
{created, Last} -> | |
Parent ! {created, Last}, | |
evaluate(Parent, M, Message); | |
Message -> | |
io:format("~w received ~w~n", [self(), Message]), | |
Parent ! Message, | |
io:format("~w sent ~w to ~w~n", [self(), Message, Parent]), | |
evaluate(Parent, M-1, Message) | |
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% | |
%% from: http://stackoverflow.com/questions/16438367/erlang-ring-controller-process-related | |
%% | |
%% | |
%% And the second one is:control spawns only the first worker in the ring. Every new worker in the ring, but the last one, spawns the next worker: | |
%% | |
-module(ring). | |
-export([start/3, start_process/1, start_process/2]). | |
start(M, N, Message) -> | |
Pid = spawn(ring, start_process, [N]), | |
Pid ! {message, Message, M}, | |
ok. | |
start_process(Count) -> | |
% This is the first spawned process - send its | |
% pid down the chain so the last process knows who its | |
% next pid is. | |
io:format("~p: Spawned ~p~n", [self(), Count]), | |
Pid = spawn(ring, start_process, [Count-1, self()]), | |
loop(Pid). | |
start_process(0, Last) -> | |
% This is the last process | |
io:format("~p: Linking to last ~p~n", [self(), Last]), | |
loop(Last); | |
start_process(Count, Last) -> | |
io:format("~p: Spawned ~p~n", [self(), Count]), | |
Pid = spawn(ring, start_process, [Count-1, Last]), | |
loop(Pid). | |
loop(NextPid) -> | |
receive | |
{message, _, 0} -> true; | |
{message, Msg, M} -> | |
io:format("~p (~p) ~p~n", [Msg, self(), M]), | |
NextPid ! {message, Msg, M-1}, | |
loop(NextPid) | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment