elixir - Can't reproduce "start/loop" behaviour in GenServer -


i'm trying use process synchronisation mechanism can receive messages our of order still act properly. i've managed implement simplified version of problem plain process, i'm failing achieve same effect genserver.

the simplified version this:

defmodule fun   def start_link     spawn(fn -> loop(:initiated) end)   end    def loop(state)     receive       :join when state == :initiated ->         io.inspect("handling join")         loop(:initiated)        :finish when state == :initiated ->         io.inspect("finishing")         loop(:finishing)        :cleanup when state == :finishing ->         io.inspect("cleaning up...")     end   end end 

the above process :join , :finish messages when state :initiated, , perform :cleanup , exit when :finish has been received. here i'm trying take advantage of messages being stuck in mailbox until can matched.

it works this:

iex(1)> pid = fun.start_link #pid<0.140.0> iex(2)> send(pid, :join) "handling join" :join iex(3)> send(pid, :join) "handling join" :join iex(4)> send(pid, :cleanup) # no `io.inspect` @ point :cleanup iex(5)> send(pid, :finish) # 2 `io.inspect`s once `:finish` received "finishing" :finish "cleaning up..." 

i trying reproduce same behaviour genserver:

defmodule funserver   use genserver    def start_link     genserver.start_link(__module__, :ok, name: __module__)   end    def init(:ok)     {:ok, :initiated}   end    def handle_info(:join, msg) when msg == :initiated     io.inspect("handling join [from genserver]")     {:noreply, :initiated}   end    def handle_info(:finish, msg) when msg == :initiated     io.inspect("finishing [from genserver]")     {:noreply, :finishing}   end    def handle_info(:cleanup, msg) when msg == :finishing     io.inspect("cleaning [from genserver]")     {:stop, :normal, msg}   end end 

given configured application genserver :temporary worker works this:

iex(1)> send(funserver, :join) "handling join [from genserver]" :join iex(2)> send(funserver, :cleanup) :cleanup iex(3)> 07:11:17.383 [error] genserver funserver terminating ** (functionclauseerror) no function clause matching in  funserver.handle_info/2     (what_the_beam) lib/fun_server.ex:22: funserver.handle_info(:cleanup, :initiated)     (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4     (stdlib) gen_server.erl:686: :gen_server.handle_msg/6     (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3 last message: :cleanup state: :initiated 

i've tried using handle_cast callbacks, , different format of arguments, like:

handle_info(:cleanup, :finishing) 

or

handle_cast(:cleanup, :finishing) 

instead of where msg == :finishing, none of them worked me.

i'm using elixir 1.5 erlang 20.

the problem running called selective recieve of regular erlang processes. quote joe armstrong's book:

    receive works follows:     ...     2. take first message in mailbox , try match      against pattern1, pattern2, , on. if match succeeds,      message removed mailbox, , expressions      following pattern evaluated.     3. if none of patterns in receive statement matches      first message in mailbox, first message removed      mailbox , put “save queue.” second message     in mailbox tried. procedure repeated until      matching message found or until messages in mail-      box have been examined.     4. if none of messages in mailbox matches, process      suspended , rescheduled execution next time      new message put in mailbox. note when new message      arrives, messages in save queue not rematched;      new message matched.     5. message has been matched, messages      have been put save queue reentered mailbox      in order in arrived @ process. if timer      set, cleared.     6. if timer elapses when waiting message,      evaluate expressions expressionstimeout , put saved      messages mailbox in order in      arrived @ process. 

gen_server not working way. needs callback module match message or found out there error thrown because gen_server implementation not finding way dispatch. if want gen_server implementation match logic of receive outlined above have manually. simple way accumulate messages can not match in given state in sort of list , resend them self() after each successful match. state can not simple atom anymore because need organize saved queue on own.

and btw same question asked before in context of erlang. responder had suggestion 1 one described. if need concrete code here link question: how do selective receives in gen_servers?


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -