How could a wrapper function be written in Elixir ?
Wrapping what?
Isn’t each function just wrapping function calls for you?
def wrapper(arg), do: wrapped(arg)
I have two processes which are calling each other as an argument by process name. For this to be done the registration of the pid with the process name is required for each process. However:
- You cannot register a process with a process name given that the process has not yet been created
- I cannot spawn the processes as arguments of each other since they are not yet registered.
It looks like a circular dependency.
Workers usually don’t spawn each other, but a Supervisor might…
What you are trying to do inherently requires knowing the identity of something before its created. Its nothing to do with Elixir.
Usual interaction between process is that there will be a server with a registered name or pid, and the client initiate the communication by sending a message to it. If you use GenServer it has the basic ingredients required for this type of interaction.
If you don’t want to use gen_servers. you might consider something like this.
def foo_loop(bar_pid) do
## useful work with bar_pid
end
def foo_init do
receive do
bar_pid ->
foo_loop(bar_pid)
end
end
foo = spawn_link(fn -> foo_init() end)
spawn_link(fn ->
send(foo, self())
## useful work
end)
Then you need a third process that knows the two pids and send them to each other process.
For example if your two processes are GenServers, they can return {:ok, state, {:continue, some_fun}}
from the init
callback, and in handle_continue you would receive
the other process pid.
Doing so in a supervision with all_for_one strategy tree ensures that this mechanism is repeated whenever one process crashes (so its pid would change after restart)
Other answers about starting and registering the processes beforehand are on point. But I am curious: how does this related to a wrapper function? Maybe you can show us your current non-working solution, so we can help you figure out how to better do that.
This is the problem I have, that :
def main() do
pid1 = spawn_link(fn -> Module.p(q) end)
pid2 = spawn_link(fn -> Module.q(p) end)
register(pid1, :p)
register(pid2, :q)
end
However the names p and q are need to be used in line 2 and 3, but they still have not been registered.
Those two processes don‘t start at the same time. So at least one of them needs to wait for the other process. You‘d likely have a better time decoupling starting/registering the processes from starting any business logic, e.g. by using genservers instead of plain processes.