<div dir="ltr"><div><div>Hi!<br><br></div>gen_fsm will be deprecated in OTP 20, so I recommend using gen_statem instead. In gen_statem you can have the semantics of selective receive by using postpone.<br><br></div>Regards Ingela  <br><div><div><div><div class="gmail_extra"> <br><br><div class="gmail_quote">2017-04-20 22:34 GMT+02:00 Stavros Filargyropoulos <span dir="ltr"><<a href="mailto:stafil@gmail.com" target="_blank">stafil@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Hey,<br><br></div>Just starting out on erlang, and trying to implement a message broker using erlang. I have a gen_fsm process for each client that handles the command and data receiving and I was wondering what is the best way to for the main broker process to send data to the client. <br><br>Do I just send a message to the client process and handle the sending inside `handle_info`? How would I handle race conditions in this case? E.g. When the client process terminates just after the main process sent the message.<br></div><div><br></div><div>My code looks something like this at the moment:<br><br>-module(pq_test).<br>-export([init/1,handle_info/3,<wbr>handle_event/3]).<br>-export([start/0]).<br>-export([recv_cmd/2,recv_data/<wbr>2]).<br><br>-record(state, {socket, buffer, current_command}).<br><br>start() -><br>    spawn_link(fun start_link/0).<br><br>start_link() -><br>    {ok, ListenSocket} = gen_tcp:listen(11880, [{active, false}, binary]),<br>    accept(ListenSocket).<br><br>accept(ListenSocket) -><br>    {ok, Socket} = gen_tcp:accept(ListenSocket),<br>    {ok, Pid} = gen_fsm:start_link({local, ?MODULE}, ?MODULE, Socket, []),<br>    erlang:display(Pid),<br>    gen_tcp:controlling_process(<wbr>Socket, Pid),<br>    accept(ListenSocket).<br><br>init(Socket)-><br>    inet:setopts(Socket, [{active, true}]),<br>    {ok, recv_cmd, <br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>cmd_parse(publish, [Topic, Key, Length], #state{socket = Socket})-><br>    {Len, _} = string:to_integer(Length),<br>    erlang:display(Len),<br>    io:format("Publish -~s- -~s- -~B-~n", [Topic, Key, Len]),<br>    {next_state, recv_data, <br>     #state{socket = Socket, buffer = <<"">>, current_command = {publish, Len}}};<br>cmd_parse(_, _, #state{socket = Socket}) -><br>    io:format("Unknown command~n"),<br>    {next_state, recv_cmd, <br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>cmd_process(CommandLine, #state{socket = Socket} = State) -><br>    io:format("1~n"),<br>    case string:tokens(binary_to_list(<wbr>CommandLine), [$\s, $\r, $\n]) of<br>    [Command | Args] -> <br>        cmd_parse(list_to_atom(<wbr>Command), Args, State);<br>    _ -> {next_state, recv_cmd, <br>          #state{socket = Socket, buffer = <<"">>, current_command = null}}<br>    end.<br><br>cmd_more(CommandLine, #state{socket = Socket}) -><br>    {next_state, recv_cmd, <br>     #state{socket=Socket, buffer=CommandLine, current_command = null}}.<br><br>recv_cmd({data, Data}, #state{buffer = Buffer} = State) -><br>    CommandLine = <<Buffer/binary, Data/binary>>,<br>    Last = binary:last(CommandLine),<br>    case Last of<br>    $\n -> cmd_process(CommandLine, State);<br>    _  -> cmd_more(CommandLine, State)<br>    end.<br><br>recv_data({data, Data}, <br>      #state{socket = Socket, <br>         buffer = Buffer, <br>         current_command = {publish, Len}}) when Len > byte_size(Data) -><br>    {next_state, recv_data,<br>     #state{socket = Socket, buffer = <<Buffer/binary, Data/binary>>, <br>        current_command = {publish, Len - byte_size(Data)}}};<br>recv_data({data, Data}, #state{socket = Socket, buffer = Buffer}) -><br>    io:format("Got all data: ~s~n", [<<Buffer/binary, Data/binary>>]),<br>    {next_state, recv_cmd,<br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>handle_info({tcp, _, Message}, StateName, State) -><br>    ?MODULE:StateName({data, Message}, State);<br>handle_info(Event, StateName, State) -><br>    io:format("handle info~n"),<br>    erlang:display(Event),<br>    {next_state, StateName, State}.<br><br>handle_event(_, _, _) -><br>    io:format("handle event").<br><br></div></div>
<br>______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-questions</a><br>
<br></blockquote></div><br></div></div></div></div></div>