this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add send/receive/server (WIP)

garrison daee0828 669af4d6

+144 -3
+41 -3
lib/trinity/scheduler.ex
··· 56 56 end 57 57 end 58 58 59 - @simulation_key :_trinity_simulation 59 + defmacro simulation_key, do: :_trinity_simulation 60 60 61 - defp get_sim, do: Process.get(@simulation_key) 62 - defp put_sim(%Simulation{} = sim), do: Process.put(@simulation_key, sim) 61 + defp get_sim, do: Process.get(simulation_key()) 62 + defp put_sim(%Simulation{} = sim), do: Process.put(simulation_key(), sim) 63 63 64 64 @spec start :: :ok 65 65 def start do ··· 130 130 # Yield to the child (or anything else in queue before it) 131 131 yield(0) 132 132 spawned_pid 133 + end 134 + 135 + defmacro receive_yield(blocks) do 136 + do_block = Keyword.fetch!(blocks, :do) 137 + 138 + {timeout, timeout_value} = 139 + case Keyword.get(blocks, :after) do 140 + nil -> {:infinity, nil} 141 + [{:->, _meta, [[timeout], timeout_value]}] -> {timeout, timeout_value} 142 + end 143 + 144 + quote do 145 + ref = make_ref() 146 + receive_fun = fn -> 147 + receive do 148 + unquote(do_block) 149 + after 150 + 0 -> ref 151 + end 152 + end 153 + 154 + case Trinity.Scheduler.receive_loop(receive_fun, ref, unquote(timeout)) do 155 + # We re-use the same ref to detect a timeout 156 + ^ref -> unquote(timeout_value) 157 + value -> value 158 + end 159 + end 160 + end 161 + 162 + @doc false 163 + def receive_loop(receive_fun, ref, timeout) do 164 + case receive_fun.() do 165 + ^ref -> 166 + # TODO: timeout 167 + receive_loop(receive_fun, ref, timeout) 168 + value -> 169 + value 170 + end 133 171 end 134 172 135 173 @spec add_link(pid) :: :ok
+5
lib/trinity/sim.ex
··· 1 + defmodule Trinity.Sim do 2 + def send(dest, message) do 3 + Kernel.send(dest, message) 4 + end 5 + end
+77
lib/trinity/sim_gen.ex
··· 1 + defmodule Trinity.SimGen do 2 + alias Trinity.Sim 3 + 4 + import Trinity.Scheduler, only: [receive_yield: 1] 5 + 6 + def start(module, init_arg, _options) do 7 + case apply(module, :init, [init_arg]) do 8 + {:ok, state} -> 9 + loop(module, state) 10 + end 11 + end 12 + 13 + defp loop(module, state) do 14 + state = receive_yield do 15 + message -> dispatch(message, module, state) 16 + end 17 + loop(module, state) 18 + end 19 + 20 + defp dispatch({:"$sim_call", {from_pid, _alias} = from, request}, module, state) do 21 + try do 22 + module.handle_call(request, from, state) 23 + catch 24 + :exit, reason -> 25 + log_exit(reason, __STACKTRACE__, state) 26 + exit(reason) 27 + end 28 + |> case do 29 + {:reply, response, state} -> 30 + Sim.send(from_pid, response) 31 + state 32 + {:noreply, state} -> 33 + state 34 + end 35 + end 36 + 37 + defp dispatch({"$:sim_cast", request}, module, state) do 38 + try do 39 + module.handle_cast(request, state) 40 + catch 41 + :exit, reason -> 42 + log_exit(reason, __STACKTRACE__, state) 43 + exit(reason) 44 + end 45 + |> case do 46 + {:noreply, state} -> 47 + state 48 + end 49 + end 50 + 51 + defp dispatch(message, module, state) do 52 + try do 53 + module.handle_info(message, state) 54 + catch 55 + :exit, reason -> 56 + log_exit(reason, __STACKTRACE__, state) 57 + exit(reason) 58 + end 59 + |> case do 60 + {:noreply, state} -> 61 + state 62 + end 63 + end 64 + 65 + defp log_exit(:normal, _stacktrace, _state), do: :noop 66 + defp log_exit(:shutdown, _stacktrace, _state), do: :noop 67 + 68 + defp log_exit(reason, stacktrace, state) do 69 + require Logger 70 + Logger.error """ 71 + SimServer #{inspect(self())} terminating 72 + ** stop #{Exception.format_exit(reason)} 73 + #{Exception.format_stacktrace(stacktrace)}\ 74 + State: #{inspect(state)}\ 75 + """ 76 + end 77 + end
+21
lib/trinity/sim_server.ex
··· 1 + defmodule Trinity.SimServer do 2 + import Trinity.Scheduler, only: [simulation_key: 0] 3 + 4 + defp get_sim, do: Process.get(simulation_key()) 5 + 6 + @spec call(GenServer.server, term, timeout) :: term 7 + def call(server, request, timeout \\ 5000) do 8 + case get_sim() do 9 + nil -> GenServer.call(server, request, timeout) 10 + _sim -> :noop 11 + end 12 + end 13 + 14 + @spec cast(GenServer.server, term) :: :ok 15 + def cast(server, request) do 16 + case get_sim() do 17 + nil -> GenServer.cast(server, request) 18 + _sim -> :noop 19 + end 20 + end 21 + end