-module(mqueue).
-export([timed_run/3]).
producer(0, ConsumerPid, _WithAck) ->
ConsumerPid ! {done, self()},
receive
done -> ok
end;
producer(N, ConsumerPid, WithAck = false) ->
ConsumerPid ! {msg, self()},
producer(N-1, ConsumerPid, WithAck);
producer(N, ConsumerPid, WithAck = true) ->
ConsumerPid ! {acked_msg, self()},
receive
ack -> ok
end,
producer(N-1, ConsumerPid, WithAck).
consumer(M, EchoPid) ->
receive
{msg, _From} ->
call_echo(M, EchoPid),
consumer(M, EchoPid);
{acked_msg, From} ->
From ! ack,
call_echo(M, EchoPid),
consumer(M, EchoPid);
{done, From} ->
EchoPid ! done,
From ! done
end.
queue_keeper_empty(ConsumerPid) ->
receive
{msg, _From} ->
ConsumerPid ! {acked_msg, self()},
queue_keeper_waiting(queue:new(), ConsumerPid);
{done, From} ->
ConsumerPid ! {done, self()},
receive
done ->
From ! done
end
end.
queue_keeper_waiting(Q, ConsumerPid) ->
receive
{msg, _From} ->
queue_keeper_waiting(
queue:in({acked_msg, self()}, Q),
ConsumerPid
);
ack -> case queue:out(Q) of
{{value, Msg}, Q1} ->
ConsumerPid ! Msg,
queue_keeper_waiting(Q1, ConsumerPid);
{empty, Q} -> queue_keeper_empty(ConsumerPid)
end
end.
call_echo(0, _EchoPid) ->
ok;
call_echo(M, EchoPid) ->
EchoPid ! {hello, self()},
receive
hello -> call_echo(M-1, EchoPid)
end.
echo() ->
receive
{Msg, From} ->
From ! Msg,
echo();
done -> ok
end.
run(N, M, WithAck) ->
EchoPid = spawn_link(fun echo/0),
ConsumerPid = spawn_link(
fun () ->
consumer(M, EchoPid) end),
case WithAck of
true ->
producer(N, ConsumerPid, WithAck);
false ->
producer(N, spawn_link(
fun() ->
queue_keeper_empty(ConsumerPid)
end
), WithAck)
end.
time(F) ->
Start = erlang:now(),
F(),
timer:now_diff(erlang:now(), Start).
timed_run(N, M, WithAck) ->
time(fun() -> run(N, M, WithAck) end).
This solution is only about 25% slower than synchronous, but producer is not blocked.
Wednesday, October 3, 2007
Keep your mailbox empty
Matthias wrote Too much mail is bad for you. Yes, it's true. He solved problem by synchronous communication between producer and consumer, but this solution blocks producer and is not "appropriate solution in general" (second comment). I think, one good solution is make your own queue manager and keep process mailbox empty. It's principally solution what recommends Vlad in that discussion. And how to do it?
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment