multithreading - How to start a gen_server or gen_fsm on demand in Erlang without race conditions? -


i need spawn several independent instances of same gen_fsm on demand, , able route calls correct instance.

gproc library seems great way of registering processes arbitrary names. has function gproc:reg_or_locate/3 spawning things on demand without race conditions. way don't need supervisor - if crash they'll spawned on demand again. can't figure out how apply gproc:reg_or_locate/3 spawning gen_fsm or gen_server.

what i've tried far:

i call gen_server:start() through function, create intermediate process, give name intermediate process, intermediate process spawn gen_server , terminate, , end nameless gen_server.

both gen_server , gen_fsm export enter_loop function seems need if feed gproc:reg_or_locate/3, documentation reads:

the process must have been started using 1 of start functions in proc_lib, see proc_lib(3).

and docs gproc:reg_or_locate/3 not mention through proc_lib.

alternatively make intermediate process acquire name , atomically transfer gen_server or gen_fsm spawned, creates race condition: intermediate process have gen_fsm's name , messages intended gen_fsm go intermediate process , lost.

i feel i'm missing simple here. it's not uncommon pattern, there should way this. did miss?

for purposes don't think gproc:reg_or_locate/3 gives useful. if returns pid (due spawning new process, or locating existing one) process still die before send message it, unless have mechanism on top of basic erlang messaging you'll never know didn't happen. server die before receiving message or die processing if alive when sent message, given express concern messages getting lost, 1 component of solution must reliable message mechanism. sensible , ready available solution gen_server:call , gen_fsm:sync_send_event in case, rather sending message.

this eliminates problem of messages getting lost spawning solution care implement. is, know message lost, or failed, , can take whatever action appropriate.

now, actual spawning of servers, there going race condition multiple processes might try , spawn same server (a server given name) no matter how implement it; to lookup name (e.g. erlang:whereis/1) out of date before else (it return pid, pid die before message it, or return undefined other process register name before try to) point @ race won (or lost) when erlang:register/2 called.

you know there might race, there can @ 1 winner. might not you, other process might beat spawning, since naming processes doesn't matter, can spawn gen_server, giving name register as, , message name:

gen_server:start({local, name}, ?module, [], []), gen_server:call(name, message) 

it doesn't matter won race (the gen_server:start/4 call might return {error,{already_started, pid}}) what, that's important should have won, , call gen_server:call has every chance of success thereafter.

you need make sure call returned suitable success result, technically check noproc exception , try spawn again, you'd have make sure doesn't become infinite loop.

to honest, although don't care supervision, i'd have supervised anyway. in case simple_one_to_one supervisor restart strategy set temporary doesn't respawn fits. servers collected in 1 place then, not floating in limbo, , you'll supervisor reports, can't bad thing. sadly won't run away restart protection because there no restarts here still need worry (unless change temporary transient). effective point of arbitration supervisor:start_child/2 , pass desired name of process parameter.


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -