OddEvenソートの並列化

、、、を、なんとか昼休み中にやろうとしたんだけれど、時間が全然足りなかった。というかカオスった。
なんとか正常動作はしているようだけれど、馬鹿すぎる設計。

%% Author: tkuro
%% Created: 2009/11/12
%% Description: odd-even parallel sort
-module(oddeven_par).

%%
%% Include files
%%
-include_lib("eunit/include/eunit.hrl").
%%
%% Exported Functions
%%
-export ([sort/1]).

%% --------------------------------------------------------------------
%% Test Functions
%% --------------------------------------------------------------------

sort_test_() ->
        [
                ?_assertEqual(sort([1,3,2]),[1,2,3]),
                ?_assertEqual(sort([3,2,0,1,5,8,4,2,2,7]),[0,1,2,2,2,3,4,5,7,8])
        ].

%% --------------------------------------------------------------------
%% Func: sort/1
%% Returns: sorted list
%% --------------------------------------------------------------------

sort(L) -> make_proc_array(L).

make_proc_array(L) ->
    make_proc_loop(none, L, true, length(L)).

make_proc_loop(Last, [], _, _) ->
    Last ! {rememberme, last},
    gather([]);
make_proc_loop(Left, [H|T], Side, N) ->
    S = self(),
    Pid = spawn_link(fun () -> sorter(S, {Left, none}, H, Side, N) end),
    make_proc_loop(Pid, T, not(Side), N).

    % (reduce)
gather(Acc) ->
    receive
        fin -> Acc;
        Val -> gather([Val|Acc])
    end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sofrter node definition %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sorter(S, {none, none}, Val, Side, N) ->
    receive
        {rememberme, R} ->
            sorter(S, {none, R}, Val, Side, N)
    end;

    % sending primary link request
sorter(S, {Left, none}, Val, Side, N) when Left =/= none ->
    Left ! {rememberme, self()},
    sorter(S, {Left, wait}, Val, Side, N);

sorter(S, {Left, wait}, Val, Side, N) ->
    receive
        {rememberme, R} ->
            sorter(S, {Left, R}, Val, Side, N)
    end;

    % finish sorting
sorter(S, Nbrs, Val, _, 0) ->
    case Nbrs of
        {Left, last} ->     % Right == last means I'm the end
            S ! Val,
            Left ! report; % ask next to report
        {none, _} ->
            receive
                report ->
                    S ! Val,
                    S ! fin
            end;
        {Left, _} ->
            receive
                report -> S ! Val,
                Left ! report  % ask next to report
            end
    end;

sorter(S, Nbrs, Val, Side, N) ->
    {Left, Right} = Nbrs,

    NSide = not(Side),
    Dir = if Side -> Right; true -> Left end,
    try pushval(Dir, Val, N) of
        _ -> void
    catch
        freespin -> sorter(S, Nbrs, Val, NSide, N-1)
    end,

    receive
        {push, Left, HisVal, N} ->
            case Val > HisVal of
                true  -> sorter(S, Nbrs, Val, NSide, N-1);
                false -> sorter(S, Nbrs, HisVal, NSide, N-1)
            end;
        {push, Right, HisVal, N} ->
            case HisVal > Val of
                true  -> sorter(S, Nbrs, Val, NSide, N-1);
                false -> sorter(S, Nbrs, HisVal, NSide, N-1)
            end
    end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

pushval(Pid, Val, N) ->
    case Pid =/= last andalso Pid =/= none of
        true -> Pid ! {push, self(), Val, N};
        false-> throw(freespin)
    end.

解説とかつけておいたほうがいろいろ直してもらえたりするのかな。。。パッと見ただけでも sorterのガードいらんよな、とか思うけど気力切れた。つかひどい過ぎてリファクタ不能な感じかも。
追記:
折角ラベルつけてたのに receiveでそれを見ていなかったのが原因だッてことに、休憩中にコーヒー飲んでて気がついた。上のコード修正しました。某先生に見つかったらウッ殺されそうな間違いでした。ごめんさい。ちゃんちゃん。