Ulf Wiger <>
Tue Jan 28 14:25:57 CET 2003

On Tue, 28 Jan 2003, Per Bergqvist wrote:

>Except that the tag is changed from '$gen_cast' to 'cast'
>etc. isn't this equivalent to a receive ... after 0 ?

OK, to follow up on the idea a step further, below's an
implementation that actually works.

The following code was written to test the new
implementation (in a gen_server callback):

handle_call(start_test, From, State) ->
    Reply = timer:tc(
	       fun({cast, _} = Msg, Acc) ->
		       {true, [Msg|Acc]};
		  (Msg, Acc) ->
	       end, []]),
    {reply, Reply, State}.

Basically gen_server:fold_messages(Fun, Acc), where
Fun(Msg, Acc) should return {true, Acc1} or false (in the
former case, the message is consumed, in the latter, not),
had the following performance on my machine:

# msgs in the queue	exec. time (us)
10			6.5
100			300
1,000			3,000
10,000			40,000

The cost is, I think, reasonable. Still, after having gotten
some sleep, I've decided that it doesn't solve the problem.
It just reduces it (possibly creating other problems in the
process.) The real problem is one of serialization, and
cannot be addressed this way. I withdraw my suggestion. Bad


fold_messages(Fun, Acc) ->
    {_, Messages} = process_info(self(), messages),
    Parent = get_parent(),
    fold(Messages, Fun, Acc, Parent).

fold([{'$gen_call',From,Request} = X|Rest], Fun, Acc, Parent) ->
    fold_one({call,From,Request}, X, Fun, Acc, Rest, Parent);
fold([{'$gen_cast',Msg} = X|Rest], Fun, Acc, Parent) ->
    fold_one({cast, Msg}, X, Fun, Acc, Rest, Parent);
fold([{'EXIT',Pid,Why} = X|Rest], Fun, Acc, Parent) when Pid /= Parent ->
    fold_one(X, X, Fun, Acc, Rest, Parent);
fold([Msg|Rest], Fun, Acc, Parent) when size(Msg) == 6,
					element(1,Msg) == system ->
    %% ignore
    fold(Rest, Fun, Acc, Parent);
fold([Msg|Rest], Fun, Acc, Parent) ->
    fold_one({info, Msg}, Msg, Fun, Acc, Rest, Parent);
fold([], _, Acc, _) ->

fold_one(Msg, X, Fun, Acc, Rest, Parent) ->
    NewAcc = case Fun(Msg, Acc) of
		 {true, Acc1} ->
		     %% consume the message
		     receive X -> X end,
		 false ->
    fold(Rest, Fun, NewAcc, Parent).

Ulf Wiger, Senior Specialist,
   / / /   Architecture & Design of Carrier-Class Software
  / / /    Strategic Product & System Management
 / / /     Ericsson Telecom AB, ATM Multiservice Networks

More information about the erlang-questions mailing list