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

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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?

  1. IsPidExists = whereis(xxx),
  2.   if IsPidExists =:= undefined ->
  3.     Pid = spawn_link(?MODULE, the_p, []),
  4.     register(xxx, Pid);
  5.     true -> true
  6.   end,



Thank you 



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

Attila Rajmund Nohl
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

bengt e
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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

bengt e
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

bengt e
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

Andreas Schultz-3
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
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:  [hidden email]
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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
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:  [hidden email]
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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

bengt e
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
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:  [hidden email]
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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

I Gusti Ngurah Oka Prinarjaya
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
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:  [hidden email]
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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

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

bengt e
Greetings,

If the intention is to always run these functions manually, one by one, then it is okay. If you want to be able to do this:
procslinked:starter(), procslinked:call_the_third().
you might get into trouble since you send init_done before you spawn the next process. Add a timer:sleep(60000) right before every spawn_link( )
and you will see the problem.

One solution is to send init_done after spawn_link().

Best Wishes,
bengt

On 13 Mar 2019, at 08:46, I Gusti Ngurah Oka Prinarjaya <[hidden email]> wrote:

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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> menulis:
I Gusti Ngurah Oka Prinarjaya <[hidden email]> 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
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:  [hidden email]
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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions