From ee0081ea72ccce060413a4bf576113b261bd25c3 Mon Sep 17 00:00:00 2001 From: garrison Date: Wed, 28 Jan 2026 14:25:53 -0500 Subject: [PATCH] Add aliases --- lib/trinity/scheduler.ex | 8 ++++ .../scheduler/simulation_supervisor.ex | 1 + lib/trinity/sim_gen.ex | 8 ++-- lib/trinity/sim_process.ex | 44 +++++++++++++++++++ lib/trinity/sim_server.ex | 12 +++-- 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 lib/trinity/sim_process.ex diff --git a/lib/trinity/scheduler.ex b/lib/trinity/scheduler.ex index 05f950d..da997ac 100644 --- a/lib/trinity/scheduler.ex +++ b/lib/trinity/scheduler.ex @@ -2,10 +2,18 @@ defmodule Trinity.Scheduler do alias Trinity.Scheduler.SimulationSupervisor defmodule Simulation do + @type t :: %__MODULE__{ + queue: :ets.table, + proc_queue_keys: :ets.table, + proc_links: :ets.table, + now: :atomics.atomics_ref, + supervisor_pid: pid, + } @enforce_keys [ :queue, :proc_queue_keys, :proc_links, + :proc_aliases, :now, :supervisor_pid, ] diff --git a/lib/trinity/scheduler/simulation_supervisor.ex b/lib/trinity/scheduler/simulation_supervisor.ex index 9d945ce..c2bcd88 100644 --- a/lib/trinity/scheduler/simulation_supervisor.ex +++ b/lib/trinity/scheduler/simulation_supervisor.ex @@ -40,6 +40,7 @@ defmodule Trinity.Scheduler.SimulationSupervisor do queue: :ets.new(__MODULE__, [:ordered_set, :public]), proc_queue_keys: :ets.new(__MODULE__, [:set, :public]), proc_links: :ets.new(__MODULE__, [:set, :public]), + proc_aliases: :ets.new(__MODULE__, [:set, :public]), now: :atomics.new(1, signed: false), supervisor_pid: self(), } diff --git a/lib/trinity/sim_gen.ex b/lib/trinity/sim_gen.ex index a57e2fe..4cb2eaa 100644 --- a/lib/trinity/sim_gen.ex +++ b/lib/trinity/sim_gen.ex @@ -1,5 +1,5 @@ defmodule Trinity.SimGen do - alias Trinity.{Scheduler, Sim} + alias Trinity.{Scheduler, SimProcess} import Trinity.Scheduler, only: [receive_yield: 1] @@ -27,7 +27,7 @@ defmodule Trinity.SimGen do defp initialize(module, init_arg, parent_pid) do case module.init(init_arg) do {:ok, state} -> - Sim.send parent_pid, {:ack, self()} + SimProcess.send parent_pid, {:ack, self()} loop(module, state) end end @@ -39,7 +39,7 @@ defmodule Trinity.SimGen do loop(module, state) end - defp dispatch({:"$sim_call", {from_pid, [:alias | _] = tag} = from, request}, module, state) do + defp dispatch({:"$sim_call", {_pid, [:alias | alias] = tag} = from, request}, module, state) do try do module.handle_call(request, from, state) catch @@ -49,7 +49,7 @@ defmodule Trinity.SimGen do end |> case do {:reply, response, state} -> - Sim.send(from_pid, {tag, response}) + SimProcess.send alias, {tag, response} state {:noreply, state} -> state diff --git a/lib/trinity/sim_process.ex b/lib/trinity/sim_process.ex new file mode 100644 index 0000000..dc0e00e --- /dev/null +++ b/lib/trinity/sim_process.ex @@ -0,0 +1,44 @@ +defmodule Trinity.SimProcess do + alias Trinity.Scheduler.Simulation + + import Trinity.Scheduler, only: [simulation_key: 0] + + @spec get_sim :: Simulation.t | nil + defp get_sim, do: Process.get(simulation_key()) + + def send(dest, message) do + Kernel.send(dest, message) + end + + @spec alias :: reference + def alias do + case get_sim() do + nil -> Process.alias() + _sim -> sim_alias() + end + end + + defp sim_alias do + %Simulation{proc_aliases: proc_aliases} = get_sim() + + alias = Process.alias() + :ets.insert(proc_aliases, {alias, self()}) + + alias + end + + @spec unalias(reference) :: boolean + def unalias(alias) do + case get_sim() do + nil -> Process.unalias(alias) + _sim -> sim_unalias(alias) + end + end + + defp sim_unalias(alias) do + %Simulation{proc_aliases: proc_aliases} = get_sim() + :ets.delete(proc_aliases, alias) + + Process.unalias(alias) + end +end diff --git a/lib/trinity/sim_server.ex b/lib/trinity/sim_server.ex index 79081af..4d5d5b8 100644 --- a/lib/trinity/sim_server.ex +++ b/lib/trinity/sim_server.ex @@ -1,5 +1,5 @@ defmodule Trinity.SimServer do - alias Trinity.{Sim, SimGen} + alias Trinity.{SimProcess, SimGen} import Trinity.Scheduler, only: [simulation_key: 0, receive_yield: 1] @@ -20,16 +20,20 @@ defmodule Trinity.SimServer do @dialyzer {:no_improper_lists, sim_call: 3} defp sim_call(server, request, timeout) do # TODO: real alias - tag = [:alias | make_ref()] + alias = SimProcess.alias() + tag = [:alias | alias] - Sim.send server, {:"$sim_call", {self(), tag}, request} + SimProcess.send server, {:"$sim_call", {self(), tag}, request} - receive_yield do + result = receive_yield do {^tag, response} -> response after # TODO timeout -> raise "timeout" end + + SimProcess.unalias(alias) + result end @spec cast(GenServer.server, term) :: :ok -- 2.51.2