"Cleaning" the message queue

Luke Gorrie luke@REDACTED
Fri Jul 13 17:32:50 CEST 2001


"Vlad Dumitrescu" <vladdu@REDACTED> writes:

> Hi all,
> 
> I have an application where processes get messages posted quite often,
> in a periodical fashion. Sometimes they don't have time to finish
> processing one message before another drops in, so the message queue
> grows longer and longer.
> 
> What I'd want is that in case there are several such messages waiting,
> only the latest shall be processed, while the rest shall be
> dumped. (The messages are "virtual clock ticks")

Here's an example program with a "receiver" process that gets 'go'
messages, and discards duplicates that pile up on its message
queue. Hopefully its pretty similar to your situation.

Since I have no information in my "go" messages I'm not actually using
the "latest" one, but that'd be an easy change.

--- SNIP ---

-module(receive_one).

-export([test/0]).

-export([receiver/0]).                  % internal

%% Test: We create a "receiver" process that will handle some 'go'
%% messages. We expect it to only actually handle two of them and
%% discard the rest, due to the timings!
%%
%% So we expect the string "Going!" should be io:format'd just twice.
test() ->
    Receiver = spawn_link(?MODULE, receiver, []),
    Receiver ! go,
    %% After this wait, the receiver will be busy processing the first
    %% 'go', allowing the next ones to accumulate in its message queue
    wait(5),
    Receiver ! go,
    Receiver ! go,
    Receiver ! go,
    Receiver ! go.

receiver() ->
    receive_go(),
    process(),
    receiver().

%% Process a 'go' message. This takes some time.
process() ->
    io:format("Going!~n"),
    %% We spend 500ms "processing" each message, so that there's time
    %% for new ones to accumulate on our message queue.
    wait(500).

%% Wait to receive a 'go' message, and flush any extra ones.
receive_go() ->
    receive
        go ->
            flush_go_msgs(),
            ok
    end.

flush_go_msgs() ->
    %% Receive/discard go messages until we timeout with 'after 0' -
    %% i.e. until no go messages are left on message queue
    receive
        go -> flush_go_msgs()
    after
        0 -> no_more_gos
    end.

wait(Time) ->
    receive
        i_never_get_this -> exit(impossible)
    after
        Time -> ok
    end.





More information about the erlang-questions mailing list