[erlang-questions] [Code Review] Is this a good idea? I linking 3 process manually (not using recursive)

I Gusti Ngurah Oka Prinarjaya okaprinarjaya@REDACTED
Wed Mar 13 08:46:05 CET 2019


Hi,

This is my updated code: https://pastebin.com/D9SAPUG8 please review again.

Please give me the pseudo code clue if there's more incorrectness to fix in
my code.

And this is the output when i run my erlang program

Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10]
[async-threads:1]


Eshell V10.2  (abort with ^G)

1> c(procslinked).

Recompiling
/Users/okaprinarjaya/Oprek/Erlang-Oprek/oprek-lagi/src/procslinked.erl

/Users/okaprinarjaya/Oprek/Erlang-Oprek/oprek-lagi/src/procslinked.erl:2:
Warning: export_all flag enabled - all functions will be exported

{ok,procslinked}

2> procslinked:starter().

Receive init_done from P1

Receive init_done from P2

Receive init_done from P3

{<0.91.0>,okbeud}

3> procslinked:call_the_first().

{<0.91.0>,"the_first_p()","Halo first p!"}

4> procslinked:call_the_second().

{<0.92.0>,"the_second_p()","Halo second p!"}

5> procslinked:call_the_third().

{<0.93.0>,"the_third_p()","Halo third p!"}

6> procslinked:call_the_first().

{<0.91.0>,"the_first_p()","Halo first p!"}

7> procslinked:call_the_second().

{<0.92.0>,"the_second_p()","Halo second p!"}

8> procslinked:call_the_third().

{<0.93.0>,"the_third_p()","Halo third p!"}

9>

Thank you :)





Pada tanggal Sel, 12 Mar 2019 pukul 02.13 bengt <cean.ebengt@REDACTED>
menulis:

> Greetings,
>
> The race is that starter/0 will return before any of the three processes
> have started. If you add a timer:sleep( 60000 ) before the calls to
> register/0 you will see this even if you do call_the_first/0 manually.
>
> The pseudo code would be
> My_pid = erlang:self(),
> P =  spawn(?MODULE, the_first_p, [My_pid]),
> receive
> {P, init_done} -> ok
> end.
>
> And then sending {erlang:self(), init_done} to My_pid (the process that
> started the_first_p).
>
>
> On 11 Mar 2019, at 12:03, I Gusti Ngurah Oka Prinarjaya <
> okaprinarjaya@REDACTED> wrote:
>
> Hi Andreas Schultz,
>
> >> The reason is that there is no guarantee that `call_the_third()` will
> be executed after any of the spawn has succeeded or the register was
> invoked.
> 1. Did you mean this code? https://pastebin.com/ECf3jhZ2
> 2. and did you mean spawn_link/3 and register/2 is racy?
> 3. I've test this code many times, and never get error in each call_the_*
> function, even call_the_third/0 function.
>
> Here: https://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrency,
> and here: https://learnyousomeerlang.com/more-on-multiprocessing and
> here: https://learnyousomeerlang.com/errors-and-processes teach me to do
> that. Oh My God, where in this earth i can read the best erlang process
> tutorial ? so i can use erlang in the right way.
>
> >> In order to get ordering guarantees you need to wait for the processes
> to be past the init stage.
> >> The normal way to do that is to wait for a message from the init
> function of you child process.
> Please give me a short pseudo-code clue to do this. I do really shocked
> because of this code: https://pastebin.com/ECf3jhZ2 still not correct
> after 2 times revision.
>
> Thank you :)
>
>
>
> Pada tanggal Sen, 11 Mar 2019 pukul 14.55 Andreas Schultz <
> andreas.schultz@REDACTED> menulis:
>
>> You do realize that your code is still "racy" ?
>>
>> Invoking it like
>>
>>     2> procslinked:starter(), procslinked:call_the_third().
>>
>> has a good chance of not producing the expected result. Most times it
>> will simply fail with:
>>
>>     ** exception error: bad argument
>>          in function  procslinked:call_the_third/0 (procslinked.erl, line
>> 54)
>>
>> The reason is that there is no guarantee that `call_the_third()` will be
>> executed after any of the spawn has succeeded or the register was invoked.
>> In order to get ordering guarantees you need to wait for the processes to
>> be past the init stage. The normal way to do that is to wait for a message
>> from the init function of you child process.
>>
>> BTW: this is exactly what proc_lib:init_ack does, but I guess you are
>> trying to implement that yourself as a learning exercise.
>>
>> Andreas
>>
>> I Gusti Ngurah Oka Prinarjaya <okaprinarjaya@REDACTED> schrieb am So.,
>> 10. März 2019 um 23:38 Uhr:
>>
>>> Hi Bengt,
>>>
>>> Thank you very much for all of your hints and suggestions. It's clear
>>> now.
>>>
>>>
>>>
>>> Pada tanggal Sen, 11 Mar 2019 05.20, bengt <cean.ebengt@REDACTED>
>>> menulis:
>>>
>>>> I think your code is about learning erlang. Do that first. OTP is the
>>>> next step.
>>>>
>>>> Yes, splitting a gen_server into callback module and interface module
>>>> is not the OTP way (as described in documentation), so while good for a
>>>> beginner it can be considered bad style by experienced programmers.
>>>>
>>>> Sorry, but I have not seen any tutorial about how to avoid thinking the
>>>> same function/module is always in the same process. It is a very
>>>> fundamental concept (them not being) in Erlang, so just keep it in mind.
>>>> One way would be to try and make all your three functions the same
>>>> function, just have different arguments to the loop. Then you must think
>>>> about it.
>>>>
>>>>
>>>> On 10 Mar 2019, at 11:11, I Gusti Ngurah Oka Prinarjaya <
>>>> okaprinarjaya@REDACTED> wrote:
>>>>
>>>> Hi Bengt,
>>>>
>>>> Thank you for your review :)
>>>>
>>>> I don't quite understand with some of your thought. Then i hope you not
>>>> mind to give more explanation.
>>>>
>>>> >> Seasoned Erlang programmers will tell you this is not the OTP way,
>>>> or a waste of modules
>>>> Did you mean my code here: https://pastebin.com/ECf3jhZ2 wasn't the
>>>> OTP way?
>>>> I learn from here: https://learnyousomeerlang.com/errors-and-processes
>>>> and i do really a beginner at programming with erlang.
>>>>
>>>> >> So only do this until you have a better understanding.
>>>> What is that? Did you mean *doing one module with the interface
>>>> functions to a gen_server and one module for the gen_server callbacks.?*
>>>> or what?
>>>>
>>>> >> Conflating the function (or even more often, module) and the process
>>>> is a common mistake in the beginning. When my fellow programmers are
>>>> experienced, but not used >> to process oriented programming.
>>>>  Any tutorials / reference for me to avoid this mistake ?
>>>>
>>>> Thank you :)
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Pada tanggal Min, 10 Mar 2019 pukul 14.49 bengt <cean.ebengt@REDACTED>
>>>> menulis:
>>>>
>>>>> Conflating the function (or even more often, module) and the process
>>>>> is a common mistake in the beginning. When my fellow programmers are
>>>>> experienced, but not used to process oriented programming, I have found
>>>>> that it helps to put the code that is run in different process in different
>>>>> modules. Ex: one module with the interface functions to a gen_server and
>>>>> one module for the gen_server callbacks. Seasoned Erlang programmers will
>>>>> tell you this is not the OTP way, or a waste of modules. So only do this
>>>>> until you have a better understanding.
>>>>>
>>>>> bengt
>>>>>
>>>>> On 10 Mar 2019, at 04:57, I Gusti Ngurah Oka Prinarjaya <
>>>>> okaprinarjaya@REDACTED> wrote:
>>>>>
>>>>> Hi Bengt,
>>>>>
>>>>> Thank you for the idea,
>>>>>
>>>>> I've implement your idea, from performance side, i think using two
>>>>> version of function will have better performance because there's no need to
>>>>> checking using IF statement.
>>>>>
>>>>> I worry at first to implement this idea, because i think different
>>>>> version of function will have different PID, hahaha it turns out exactly
>>>>> have same PID.
>>>>> this is  my new code https://pastebin.com/ECf3jhZ2 . Please review if
>>>>> there's any improvement needs.
>>>>>
>>>>> Thank you
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Pada tanggal Min, 10 Mar 2019 pukul 05.23 bengt <cean.ebengt@REDACTED>
>>>>> menulis:
>>>>>
>>>>>> Greetings,
>>>>>>
>>>>>> The error happens the second time any of the three processes call
>>>>>> erlang:register/2. They already registered themselves the first time. If
>>>>>> you want this structure, but not the error, you have to do the register
>>>>>> before starting the loop. Eg, split the functions into two. One that do the
>>>>>> register and then calls the second that does the loop.
>>>>>>
>>>>>> bengt
>>>>>>
>>>>>> On 9 Mar 2019, at 14:41, I Gusti Ngurah Oka Prinarjaya <
>>>>>> okaprinarjaya@REDACTED> wrote:
>>>>>>
>>>>>> Hi Attila Rajmund Nohl,
>>>>>>
>>>>>> After i implement your suggestion, i get error when execute any of
>>>>>> function call_the_*_p()
>>>>>> for example:
>>>>>>
>>>>>> 3> newbie:starter().
>>>>>> <0.112.0>
>>>>>> 4> newbie:call_the_second().
>>>>>> =ERROR REPORT==== 9-Mar-2019::20:35:15.069388 ===
>>>>>> Error in process <0.113.0> with exit value:
>>>>>> {badarg,[{erlang,register,[pidsecondp,<0.113.0>],[]},
>>>>>>          {newbie,the_second_p,0,
>>>>>>
>>>>>> [{file,"/Users/okaprinarjaya/Oprek/Erlang-Oprek/oprek-lagi/src/newbie.erl"},
>>>>>>                   {line,17}]}]}
>>>>>>
>>>>>> {<0.113.0>,"the_second_p()","Halo second p!"}
>>>>>>
>>>>>> This is my new modified code https://pastebin.com/iYCxkkuz
>>>>>>
>>>>>>
>>>>>> Pada tanggal Jum, 8 Mar 2019 pukul 21.03 Attila Rajmund Nohl <
>>>>>> attila.r.nohl@REDACTED> menulis:
>>>>>>
>>>>>>> I Gusti Ngurah Oka Prinarjaya <okaprinarjaya@REDACTED> ezt írta
>>>>>>> (időpont: 2019. márc. 8., P, 12:11):
>>>>>>> >
>>>>>>> > Hi Folks,
>>>>>>> >
>>>>>>> > I need your help to review my code. I create and linking 3 process
>>>>>>> manually without using recursive. And inside p1 and p2 i using IF statement
>>>>>>> to check to make sure spawning process will only once.
>>>>>>> >
>>>>>>> > I mean, is part code below is a good idea?
>>>>>>> >
>>>>>>> > IsPidExists = whereis(xxx),
>>>>>>> >   if IsPidExists =:= undefined ->
>>>>>>> >     Pid = spawn_link(?MODULE, the_p, []),
>>>>>>> >     register(xxx, Pid);
>>>>>>> >     true -> true
>>>>>>> >   end,
>>>>>>>
>>>>>>> Generally this is not a good idea, there's a race condition between
>>>>>>> checking that the process is registered (the whereis/1 call) and
>>>>>>> registering the new process. A better idea is to start the process
>>>>>>> and
>>>>>>> let the process itself to register. If register fails, it means that
>>>>>>> there's already a process registered, so the just started process can
>>>>>>> terminate. So your code could look like something like this:
>>>>>>>
>>>>>>> starter() ->
>>>>>>>   spawn(?MODULE, the_first_p, []).
>>>>>>>
>>>>>>> the_first_p() ->
>>>>>>>   register(pidfirstp, self()),
>>>>>>>   spawn_link(?MODULE, the_second_p, []),
>>>>>>>   ...
>>>>>>>   the_first_p().
>>>>>>>
>>>>>>> Actually if the register call fails, it throws a badarg and the
>>>>>>> process dies automatically, simplifying the code.
>>>>>>>
>>>>>> _______________________________________________
>>>>>> erlang-questions mailing list
>>>>>> erlang-questions@REDACTED
>>>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> erlang-questions mailing list
>>>>>> erlang-questions@REDACTED
>>>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> erlang-questions mailing list
>>>>> erlang-questions@REDACTED
>>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>>
>>>>
>>>> _______________________________________________
>>>> erlang-questions mailing list
>>>> erlang-questions@REDACTED
>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> erlang-questions@REDACTED
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>> --
>> --
>> Dipl.-Inform. Andreas Schultz
>>
>> ----------------------- enabling your networks ----------------------
>> Travelping GmbH                     Phone:  +49-391-81 90 99 0
>> Roentgenstr. 13                     Fax:    +49-391-81 90 99 299
>> 39108 Magdeburg                     Email:  info@REDACTED
>> GERMANY                             Web:    http://www.travelping.com
>>
>> Company Registration: Amtsgericht Stendal        Reg No.:   HRB 10578
>> Geschaeftsfuehrer: Holger Winkelmann          VAT ID No.: DE236673780
>> ---------------------------------------------------------------------
>>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20190313/1bb86e14/attachment.htm>


More information about the erlang-questions mailing list