Packages

A reactive programming library for Elixir. The purpose of this library is to experiment in an academic context.

Current section

Files

Jump to
reactivity lib reactive_registry.ex
Raw

lib/reactive_registry.ex

defmodule Reactivity.Registry do
use GenServer
require Logger
alias Reactivity.Signal.Source
alias Reactivity.Signal.Derived
#############
# GenServer #
#############
def start_link(args \\ []) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def init(args) do
table = :ets.new(:sources, [:named_table, :set, :protected])
{:ok, %{:table => table, :subs => MapSet.new()}}
end
#############
# Callbacks #
#############
def handle_cast(m, state) do
Logger.debug "Cast: #{inspect m}"
{:noreply, state}
end
def handle_call({:insert, source, name}, _from, %{:table => t} = state) do
:ets.insert(t, {name, source})
publish_new_signal(source, name, state)
{:reply, :ok, state}
end
def handle_call({:remove, name}, _from, %{:table => t} = state) do
:ets.delete(t, name)
{:reply, :ok, state}
end
def handle_call({:get, name}, _from, %{:table => t} = state) do
case :ets.lookup(t, name) do
[{^name, val}] -> {:reply, {:ok, val}, state}
[] -> {:reply, {:error, "not found"}, state}
end
end
def handle_call({:subscribe, pid}, _from, %{:subs => ss} = state) do
Logger.debug "Adding subscription for #{inspect pid}"
{:reply, :ok, %{state | :subs => MapSet.put(ss, pid)}}
end
def handle_call({:unsubscribe, pid}, _from, %{:subs => ss} = state) do
{:reply, :ok, %{state | :subs => MapSet.delete(ss, pid)}}
end
def handle_call(m, from, state) do
Logger.debug "Call: #{inspect m} from #{inspect from}"
{:reply, :ok, state}
end
def handle_info(m, state) do
Logger.debug "Info: #{inspect m}"
{:noreply, state}
end
###########
# Private #
###########
defp publish_new_signal(source, name, %{:subs => ss} = state) do
ss
|> Enum.map(fn(sub) -> send(sub, {:new_signal, source, name}) end)
end
#############
# Interface #
#############
def add_source(source, name) do
GenServer.call(__MODULE__, {:insert, source, name})
end
def remove_source(name) do
GenServer.call(__MODULE__, {:remove, name})
end
def get_source(name) do
GenServer.call(__MODULE__, {:get, name})
end
def subscribe(pid) do
GenServer.call(__MODULE__, {:subscribe, pid})
end
def unsubscribe(pid) do
GenServer.call(__MODULE__, {:unsubscribe, pid})
end
end