Current section

Files

Jump to
chip src chip@registry.erl
Raw

src/chip@registry.erl

-module(chip@registry).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([register/3, find/2, start/0]).
-export_type([message/2, index/0, state/2]).
-opaque message(HJZ, HKA) :: {tag,
gleam@erlang@process:subject({ok, gleam@erlang@process:subject(HKA)} |
{error, nil}),
HJZ} |
{registrant, gleam@erlang@process:subject(HKA), HJZ} |
{demonitor, index()}.
-type index() :: {index,
gleam@erlang@process:pid_(),
gleam@erlang@process:process_monitor()}.
-type state(HKB, HKC) :: {state,
gleam@erlang@process:subject(message(HKB, HKC)),
gleam@dict:dict(HKB, gleam@erlang@process:subject(HKC)),
gleam@dict:dict(gleam@erlang@process:pid_(), gleam@set:set(HKB)),
gleam@erlang@process:selector(message(HKB, HKC))}.
-spec register(
gleam@erlang@process:subject(message(HKO, HKP)),
gleam@erlang@process:subject(HKP),
HKO
) -> nil.
register(Registry, Subject, Name) ->
gleam@erlang@process:send(Registry, {registrant, Subject, Name}).
-spec find(gleam@erlang@process:subject(message(HKV, HKW)), HKV) -> {ok,
gleam@erlang@process:subject(HKW)} |
{error, nil}.
find(Registry, Name) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {tag, _capture, Name} end,
10
).
-spec handle_init() -> gleam@otp@actor:init_result(state(HOT, HOS), message(HOT, HOS)).
handle_init() ->
Self = gleam@erlang@process:new_subject(),
State = {state,
Self,
gleam@dict:new(),
gleam@dict:new(),
begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:selecting(
_pipe,
Self,
fun gleam@function:identity/1
)
end},
{ready, State, erlang:element(5, State)}.
-spec into_names(state(HLI, HLJ), HLI, gleam@erlang@process:subject(HLJ)) -> state(HLI, HLJ).
into_names(State, Name, Subject) ->
erlang:setelement(
3,
State,
gleam@dict:insert(erlang:element(3, State), Name, Subject)
).
-spec into_tracker(state(HLP, HLQ), gleam@erlang@process:pid_(), HLP) -> state(HLP, HLQ).
into_tracker(State, Pid, Location) ->
Add_location = fun(Option) -> case Option of
{some, Locations} ->
gleam@set:insert(Locations, Location);
none ->
gleam@set:insert(gleam@set:new(), Location)
end end,
erlang:setelement(
4,
State,
gleam@dict:update(erlang:element(4, State), Pid, Add_location)
).
-spec into_selector(
state(HLV, HLW),
gleam@option:option(gleam@erlang@process:selector(message(HLV, HLW)))
) -> state(HLV, HLW).
into_selector(State, Selection) ->
case Selection of
{some, Selector} ->
erlang:setelement(5, State, Selector);
none ->
State
end.
-spec remove_from_group(state(HMF, HMG), gleam@erlang@process:pid_()) -> state(HMF, HMG).
remove_from_group(State, Pid) ->
Names = case gleam@dict:get(erlang:element(4, State), Pid) of
{ok, Locations} ->
gleam@set:to_list(Locations);
{error, nil} ->
erlang:error(#{gleam_error => panic,
message => <<"Impossible state, couldn't find a pid when removing from group."/utf8>>,
module => <<"chip/registry"/utf8>>,
function => <<"remove_from_group"/utf8>>,
line => 181})
end,
gleam@list:fold(
Names,
State,
fun(State@1, Name) ->
Names@1 = gleam@dict:delete(erlang:element(3, State@1), Name),
erlang:setelement(3, State@1, Names@1)
end
).
-spec remove_from_tracker(state(HML, HMM), gleam@erlang@process:pid_()) -> state(HML, HMM).
remove_from_tracker(State, Pid) ->
erlang:setelement(
4,
State,
gleam@dict:delete(erlang:element(4, State), Pid)
).
-spec select_process_down(
gleam@erlang@process:selector(message(HMZ, HNA)),
gleam@erlang@process:pid_(),
gleam@erlang@process:process_monitor()
) -> gleam@erlang@process:selector(message(HMZ, HNA)).
select_process_down(Selector, Pid, Monitor) ->
Index = {index, Pid, Monitor},
Handle = fun(_) -> {demonitor, Index} end,
gleam@erlang@process:selecting_process_down(Selector, Monitor, Handle).
-spec monitor(state(HMR, HMS), gleam@erlang@process:pid_()) -> gleam@option:option(gleam@erlang@process:selector(message(HMR, HMS))).
monitor(State, Pid) ->
case gleam@dict:get(erlang:element(4, State), Pid) of
{ok, _} ->
none;
{error, nil} ->
Monitor = gleam@erlang@process:monitor_process(Pid),
Selector = select_process_down(
erlang:element(5, State),
Pid,
Monitor
),
{some, Selector}
end.
-spec handle_message(message(HLB, HLC), state(HLB, HLC)) -> gleam@otp@actor:next(message(HLB, HLC), state(HLB, HLC)).
handle_message(Message, State) ->
case Message of
{tag, Client, Name} ->
Result = gleam@dict:get(erlang:element(3, State), Name),
gleam@erlang@process:send(Client, Result),
gleam@otp@actor:continue(State);
{registrant, Subject, Name@1} ->
Pid = gleam@erlang@process:subject_owner(Subject),
Selection = monitor(State, Pid),
_pipe = State,
_pipe@1 = into_names(_pipe, Name@1, Subject),
_pipe@2 = into_tracker(_pipe@1, Pid, Name@1),
_pipe@3 = into_selector(_pipe@2, Selection),
{continue, _pipe@3, Selection};
{demonitor, {index, Pid@1, Monitor}} ->
gleam_erlang_ffi:demonitor(Monitor),
_pipe@4 = State,
_pipe@5 = remove_from_group(_pipe@4, Pid@1),
_pipe@6 = remove_from_tracker(_pipe@5, Pid@1),
gleam@otp@actor:continue(_pipe@6)
end.
-spec start() -> {ok, gleam@erlang@process:subject(message(any(), any()))} |
{error, gleam@otp@actor:start_error()}.
start() ->
gleam@otp@actor:start_spec(
{spec, fun handle_init/0, 10, fun handle_message/2}
).