diff --git a/lib/trinity/scheduler.ex b/lib/trinity/scheduler.ex index a7a2ca4..4e487e9 100644 --- a/lib/trinity/scheduler.ex +++ b/lib/trinity/scheduler.ex @@ -48,10 +48,6 @@ defmodule Trinity.Scheduler do @spec get_sim :: Simulation.t defp get_sim, do: Process.get(simulation_key()) - def run_simulation(fun) do - SimulationSupervisor.run_simulation(fun) - end - @spec now :: integer def now do %{now: now} = get_sim() diff --git a/lib/trinity/scheduler/simulation_supervisor.ex b/lib/trinity/scheduler/simulation_supervisor.ex index 4f5e9f6..eaa0a07 100644 --- a/lib/trinity/scheduler/simulation_supervisor.ex +++ b/lib/trinity/scheduler/simulation_supervisor.ex @@ -15,10 +15,11 @@ defmodule Trinity.Scheduler.SimulationSupervisor do defstruct @enforce_keys end - @spec run_simulation(function) :: :ok - def run_simulation(fun) do + @spec run_simulation(function, %{seed: integer}) :: :ok + def run_simulation(fun, %{seed: seed}) do ref = make_ref() GenServer.start_link(__MODULE__, %{ + seed: seed, fun: fun, parent_pid: self(), parent_ref: ref, @@ -37,8 +38,9 @@ defmodule Trinity.Scheduler.SimulationSupervisor do GenServer.call(server, {:spawn_child, fun}) end - def init(%{fun: fun, parent_pid: parent_pid, parent_ref: parent_ref}) do + def init(%{seed: seed, fun: fun, parent_pid: parent_pid, parent_ref: parent_ref}) do Process.flag(:trap_exit, true) + :rand.seed(:exsss, seed) sim = %Simulation{ queue: :ets.new(__MODULE__, [:ordered_set, :public]), @@ -148,7 +150,10 @@ defmodule Trinity.Scheduler.SimulationSupervisor do end defp spawn_sim_child(%Simulation{} = sim, fun) do + # TODO: larger range? + child_seed = Enum.random(1..1_000_000) spawn_link(fn -> + :rand.seed(:exsss, child_seed) Process.put(simulation_key(), sim) fun.() end) diff --git a/lib/trinity/sim.ex b/lib/trinity/sim.ex index 2862f67..b3739c7 100644 --- a/lib/trinity/sim.ex +++ b/lib/trinity/sim.ex @@ -5,6 +5,12 @@ defmodule Trinity.Sim do @spec get_sim :: Simulation.t | nil defp get_sim, do: Process.get(simulation_key()) + @spec run_simulation(function, keyword) :: :ok + def run_simulation(fun, opts \\ []) do + seed = Keyword.get(opts, :seed, 100) + Trinity.Scheduler.SimulationSupervisor.run_simulation(fun, %{seed: seed}) + end + @spec simulated? :: boolean def simulated? do case get_sim() do diff --git a/test/trinity_test.exs b/test/trinity_test.exs index 2c9a0e5..60bd16c 100644 --- a/test/trinity_test.exs +++ b/test/trinity_test.exs @@ -1,7 +1,7 @@ defmodule TrinityTest do use ExUnit.Case - alias Trinity.{SimProcess, SimLogger, Scheduler} + alias Trinity.{Sim, SimProcess, SimLogger, Scheduler} import Trinity.Scheduler, only: [receive_yield: 1] require SimLogger @@ -53,7 +53,7 @@ defmodule TrinityTest do end test "scheduler" do - Scheduler.run_simulation(fn -> + Sim.run_simulation(fn -> nodes = [:n1, :n2, :n3] pids = Enum.map(nodes, fn node -> @@ -98,6 +98,6 @@ defmodule TrinityTest do Scheduler.yield(1000) #dbg Scheduler.dump(), limit: :infinity - end) + end, seed: 101) end end