What is the purpose of entering "save queue" in erlang retrieval instructions

I am new to erlang and starting a tutorial from Joe Armstrong's “Programming Erlang”.

I am perplexed about the “save queue” mentioned in the selective receipt in 8.6. If the message does not match at all, why not delete it directly? What is the purpose of returning it to the mailbox for further processing? If this is the default behavior, these garbage messages (which means that they cannot be matched) can result in performance penalties as they will accumulate without release.

I would like to know if I did not understand this part. I tried to check the contents of the process mailbox to get a better understanding, but I could not.

Please help, I would appreciate any piece of code that proves the point, thanks.

+5
source share
3 answers

This section of the book describes the details of what is done by one receiving unit. Do not forget that it is possible that several receiving units are processed sequentially by one process, therefore a single message that does not correspond to any record of the first receiving unit will be placed in the save queue (for efficiency), because:

  • it will never match any element of the current receive block,
  • the current receiving unit is guaranteed to complete only when one incoming message matches one record or a timeout expires.

, , , " ".

- :

loop() ->
   ...
   receive
      {high_prio,Msg} -> process_priority_message(Msg)
   after 0
      ok  % no priority message
   end,

   receive
      {low_prio,Msg} -> process_normal_message(Msg);
      Other -> process_unexpected_message(Other)
   end,
   ...
   loop()

{high_prio, Msg}, .

, , , , -

→ process_unexpected_message ()

.

+11

, , , . Erlang , , . , , , . .

. , . . , . . Erlang , , . , .

, - , . , gen_server , ( ), "" ( ), , , .

.

, , / , , gen_server s. , .

, , , , , , . , , . A gen_server , , , ( ) , .

, @Pascal.

+3

+1 to rvirding: " " . - "" - . , :

-module(smokers).
-export([smokers/0]).

smokers() ->
    Rounds = 1000000,
    Agent = self(),
    lists:foreach(fun(Material) -> spawn(fun() -> startSmoker(Agent, Material) end) end, materials()),
    done = agent(Rounds),
    io:format("Done ~p rounds~n", [Rounds]).

agent(0) ->
    done;
agent(Rounds) ->
    offer(twoRandomMaterials(), Rounds).

offer(AvailableMaterials, Rounds) ->
    receive
        {take, Smoker, AvailableMaterials} ->
            Smoker ! smoke,
            receive
                doneSmoking ->
                    agent(Rounds - 1)
            end
    end.

startSmoker(Agent, Material) ->
    smoker(Agent, lists:delete(Material, materials())).

smoker(Agent, Missing) ->
    Agent ! {take, self(), Missing},
    receive
        smoke ->
            Agent ! doneSmoking,
            smoker(Agent, Missing)
    end.

twoRandomMaterials() ->
    Materials = materials(),
    deleteAt(random:uniform(length(Materials)) - 1, Materials).

materials() ->
    [paper, tobacco, match].

deleteAt(_, []) -> [];
deleteAt(0, [_ | T]) -> T;
deleteAt(Idx, [H | T]) -> [H | deleteAt(Idx - 1, T)].

Interestingly, there are potentially three messages in this queue when we try to use receive {take, Smoker, AvailableMaterials}. However, only one of them can be processed. Then there is an inner handshake receive doneSmoking. Thus, the selection of appropriate messages, allowing the code to do some work at all, and also not to lose other messages takewhen receiving a confirmation message, is what solves all concurrency problems here. If messages that did not match / were not processed were discarded at any time, smokerthey would be stuck forever (if they would not repeat their requests periodically).

+1
source

All Articles