Using atoms as pids in Elixir
When starting a GenServer process via its start_link/3
API, we're given a pid when the call succeeds:
{:ok, pid} = GenServer.start_link(MyModule, %{})
# {:ok, #PID<0.980.0>}
A call to start_link/3
is often abstracted into the GenServer module that is being created.
If we want to only start a single process for our module in our application, we can utilize the name
option:
defmodule MyModule do
use GenServer
@impl true
def init(state), do: {:ok, state}
def start_link(state) do
GenServer.start_link(
__MODULE__,
state,
name: __MODULE__
)
end
end
This works because __MODULE__
maps to an atom.
If we wanted to, we can improve our start_link/2
method to accept an atom as a name. We can then use the name
variable as our pid when implementing our callbacks:
defmodule MyModule do
use GenServer
@impl true
def init(state), do: {:ok, state}
def start_link(state) do
GenServer.start_link(
__MODULE__,
state,
name: __MODULE__
)
end
def perform_work(pid), do:
GenServer.cast(pid, {:work})
@impl true
def handle_cast({:work}, state) do
## Do the thing in here!
end
end
But since we have an atom that maps to the process identifier, we can simply invoke it like so:
{:ok, _} = MyModule.start_link(:worker, %{})
MyModule.perform_work(:worker)