uwiger / gproc

Extended process registry for Erlang
Apache License 2.0
1.07k stars 232 forks source link

Change send/2 so that it returns the pid or pids the message was sent to #34

Closed jcomellas closed 11 years ago

jcomellas commented 11 years ago

To use gproc to register names using the via mechanism that was recently added to OTP (gen_server, gen_fsm, gen_event) it must provide a send/2 function that can be used to implement the function with the following type spec:

send(Name :: term(), Msg :: term()) -> pid().

Currently gproc:send/2 returns the message that was sent. This patch changes it so that the new type spec for it is:

send(Name :: term(), Msg :: term()) -> pid() | [pid()].

It will now return the pid or list of pids the message was sent to.

I know this is a backward incompatible change, so I will send another pull request in a few minutes that will add a new function called send_to_name/2 instead of changing send/2.

jcomellas commented 11 years ago

I'd prefer this patch to go in instead of the one I sent afterwards, as it would allow gproc to be used as a drop-in name registry with OTP.

uwiger commented 11 years ago

It is true that global:send/2 -> pid(), but the OTP behaviors all ignore the return value of Mod:send/2 (even wrap it inside a catch).

The most backward compatible change would therefore be to change the OTP documentation.

The OTP documentation is fairly vague on the subject already:

The Module callback should export the functions register_name/2, unregister_name/1, whereis_name/1 and send/2, which should behave like the corresponding functions in global.

jcomellas commented 11 years ago

I agree, and there should probably be a behaviour for OTP name registries.

Do you think the OTP team would be willing to make this change?

BTW, I see the return of the pids the message was sent to as something much more useful than the message that was sent. The caller already has the message and will probably never use that return value, whereas it might come in handy to know which processes received your message.

uwiger commented 11 years ago

This is true, but returning a pid like global still wouldn't work, since gproc:send/2 can (in the case of using a property) send to several processes. The most useful return value then might be a list of all pids that were sent the message.

Returning the message itself of course mimicks the erlang send operator (!). In the case of !, this property can be use to write stuff like P1 ! P2 ! P3 ! P4 ! Msg.

Not that I imagine anyone ever does...

jcomellas commented 11 years ago

If you look at the patch you'll see that if you send a message to multiple processes you'll actually receive the list of pids the message was sent to.

uwiger commented 11 years ago

Well, yes, but the question then is whether there is sufficient justification for an API change.

uwiger commented 11 years ago

I will close this issue, as the return value of gproc:send/2 is ignored by the OTP behaviors (even though it's not documented as such). OTP already has a 'conflict' as global:send(P,Msg) -> pid(), whereas erlang:send(P,Msg) -> Msg, and I'm reluctant to make an API change when the current API actually doesn't break anything (but actually changing it might).

Thanks for pointing out the issue with the {via, ...} construct, though. It should be clarified.