ErlangでWorker Threadパターン

30分プログラム、その407。Java言語で学ぶデザインパターン入門 マルチスレッド編のWorker ThreadパターンをErlangでやってみる。
Worker threadパターンは要するに、スレッドをいくつか作っておいて、それを使い回わすためのパターン。プロセス生成が軽いと評判のErlangだと無駄なパターンな気がしなくもない。

使い方

% 5つのプロセスを待たせる
1> Pool = worker_thread:thread_pool(5).
Work at 1
Work at 2
Work at 3
Work at 4
Work at 5
<0.137.0>

% 1つ目のプロセスで動作させる
2> Pool ! {put,fun () -> io:format("hello~n") end}.
hello
{put,#Fun<erl_eval.20.67289768>}
Work at 1

% 2つ目のプロセスで動作させる
3> Pool ! {put,fun () -> io:format("hello~n") end}.
hello
{put,#Fun<erl_eval.20.67289768>}
Work at 2

ソースコード

-module(worker_thread).
-compile([export_all]).

queue_server(Queue) ->
    receive
	{take,From} -> 
	    case Queue of
		[] ->
		    receive
			{put,F} ->
			    From ! {get,F},
			    queue_server([])
		    end;
		[H|Tl] ->
		    From ! {get,H},
		    queue_server(Tl)
	    end;
	{put,F} ->
	    queue_server([F|Queue])
    end.

worker(Server,Id) ->
    io:format("Work at ~p~n",[Id]),
    Server ! {take,self()},
    receive
	{get,F} ->
	    F(),
	    worker(Server,Id)
    end.

thread_pool(N) ->
    Pid = spawn(fun ()->queue_server([]) end),
    [spawn(fun()-> worker(Pid,Id) end) || Id <- lists:seq(1,N)],
    Pid.