[erlang-questions] gproc

OvermindDL1 <>
Sat Feb 12 21:27:17 CET 2011


On Sat, Feb 12, 2011 at 12:35 PM, James Churchman
<> wrote:
> Firstly, gprocs great :-) should really come as part of the erlang distro!
>
> but i have two questions :
>
> "First" :
>
> -------
> first/1
>
> first(Type::type()) -> key() | '$end_of_table'
>
>
> Behaves as ets:first(Tab) for a given type of registration object.
>
> See http://www.erlang.org/doc/man/ets.html#first-1. The registry behaves as an ordered_set table.
>
> -------
>
> Why does it behave as an ordered set? does this have any advantages ? i see with select/123 you can pattern match but even in this case does it help much ? and does begin ordered strongly effect performance, especially as i am only ever using it as a (single) process registry? can you pick an unordered set if you don't need it?
>
>
> "Second" :
>
> I want to do a fairly common pattern of registering a process and using it, unless its already registered where i use the registered one
>
> so for a local registration :
>
> gproc:reg({n, l,"ID"}).
>
> however on a second (and therefor "failing" ) registration it gives
>
> exception error: bad argument: [{gproc,chk_reply,{reg,{n,l,ok2},undefined}},         {erl_eval,do_apply,5},     {shell,exprs,7},     {shell,eval_exprs,7},      {shell,eval_loop,3}]
>
> i can obviously catch this, but it would be nicer if it did the genserver style of returning {error , already_exists , PID / Value_Stored_At_That_Key}
>
> the alternate is to do a lookup first, but as ~98 % of the time in my case it wont be registered this seems a bit counter intuitive
>
> also in either case, there is a small race condition in that :
>
> 1) i look up the process, its not there, but before i register it, someone else did (so it throws... )
> 2) register the process, it exists, look it up, and in that time the process has ended its usefulness and has shutdown, so when i message it, its gone
>
> in both cases i can add extra code to register a 2nd time etc... but it seems a tad excessive
>
> are there better ways of doing things that im missing, or is this simply the way things are in a distributed multithreaded environment :-)

nprocreg (made by but is a standalone dependency of Nitrogen) does
what you want (and a bit more):  https://github.com/nitrogen/nprocreg

Just link it in, start up its sup (or application), and use it like this:

  nprocreg:get_pid(pid_name). % This will return an existing proc with
pid_name name as Pid or will return undefined

  nprocreg:get_pid(pid_name, Fun). % This will return an existing proc
with pid_name name as Pid, or will create a new process with the name
pid_name if the Fun in a fun, or will return undefined is Fun is
undefined.

The extra that it does that you may or may not want is that it
distributed processes across all connected nodes that are running
nprocreg, which may or may not be what you want.  Do not quote me on
this, but I do not think it handles nodes being dynamically
added/removed.


More information about the erlang-questions mailing list