Current section

Files

Jump to
chip src chip.erl
Raw

src/chip.erl

-module(chip).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-export([all/1, lookup/2, register/2, register_as/3, deregister/2, stop/1, start/0]).
-export_type([action/2, state/2]).
-opaque action(GYZ, GZA) :: {all,
gleam@erlang@process:subject(list(gleam@erlang@process:subject(GZA)))} |
{lookup,
gleam@erlang@process:subject(list(gleam@erlang@process:subject(GZA))),
GYZ} |
{register, gleam@erlang@process:subject(GZA)} |
{register_as, gleam@erlang@process:subject(GZA), GYZ} |
{deregister, GYZ} |
{demonitor, gleam@erlang@process:subject(GZA)} |
rebuild_selector |
{stop, gleam@erlang@process:subject(gleam@erlang@process:exit_reason())}.
-type state(GZB, GZC) :: {state,
gleam@erlang@process:subject(action(GZB, GZC)),
gleam@map:map_(gleam@erlang@process:pid_(), gleam@erlang@process:process_monitor()),
gleam@set:set(gleam@erlang@process:subject(GZC)),
gleam@map:map_(GZB, gleam@set:set(gleam@erlang@process:subject(GZC))),
gleam@erlang@process:selector(action(GZB, GZC))}.
-spec all(gleam@erlang@process:subject(action(any(), GZL))) -> list(gleam@erlang@process:subject(GZL)).
all(Registry) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {all, _capture} end,
100
).
-spec lookup(gleam@erlang@process:subject(action(GZR, GZS)), GZR) -> list(gleam@erlang@process:subject(GZS)).
lookup(Registry, Name) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {lookup, _capture, Name} end,
100
).
-spec register(
gleam@erlang@process:subject(action(any(), GZZ)),
fun(() -> {ok, gleam@erlang@process:subject(GZZ)} |
{error, gleam@otp@actor:start_error()})
) -> {ok, gleam@erlang@process:subject(GZZ)} |
{error, gleam@otp@actor:start_error()}.
register(Registry, Start) ->
gleam@result:'try'(
Start(),
fun(Subject) ->
gleam@erlang@process:send(Registry, {register, Subject}),
{ok, Subject}
end
).
-spec register_as(
gleam@erlang@process:subject(action(HAJ, HAK)),
HAJ,
fun(() -> {ok, gleam@erlang@process:subject(HAK)} |
{error, gleam@otp@actor:start_error()})
) -> {ok, gleam@erlang@process:subject(HAK)} |
{error, gleam@otp@actor:start_error()}.
register_as(Registry, Name, Start) ->
gleam@result:'try'(
Start(),
fun(Subject) ->
gleam@erlang@process:send(Registry, {register_as, Subject, Name}),
{ok, Subject}
end
).
-spec deregister(gleam@erlang@process:subject(action(HAU, any())), HAU) -> nil.
deregister(Registry, Name) ->
gleam@erlang@process:send(Registry, {deregister, Name}).
-spec stop(gleam@erlang@process:subject(action(any(), any()))) -> gleam@erlang@process:exit_reason().
stop(Registry) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {stop, _capture} end,
10
).
-spec handle_init() -> gleam@otp@actor:init_result(state(HBE, HBF), action(HBE, HBF)).
handle_init() ->
Subject = gleam@erlang@process:new_subject(),
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:selecting(
_pipe,
Subject,
fun gleam@function:identity/1
)
end,
State = {state,
Subject,
gleam@map:new(),
gleam@set:new(),
gleam@map:new(),
Selector},
{ready, State, Selector}.
-spec demonitor_subject(state(HCN, HCO), gleam@erlang@process:subject(HCO)) -> state(HCN, HCO).
demonitor_subject(State, Subject) ->
Pid = gleam@erlang@process:subject_owner(Subject),
case gleam@map:get(erlang:element(3, State), Pid) of
{ok, Monitor} ->
gleam_erlang_ffi:demonitor(Monitor),
Index = gleam@map:delete(erlang:element(3, State), Pid),
Group = gleam@set:delete(erlang:element(4, State), Subject),
Delete = fun(_, Subjects) -> gleam@set:delete(Subjects, Subject) end,
Named = gleam@map:map_values(erlang:element(5, State), Delete),
erlang:setelement(
5,
erlang:setelement(4, erlang:setelement(3, State, Index), Group),
Named
);
{error, nil} ->
State
end.
-spec get_group(
gleam@map:map_(HCU, gleam@set:set(gleam@erlang@process:subject(HCV))),
HCU
) -> gleam@set:set(gleam@erlang@process:subject(HCV)).
get_group(Named, Name) ->
case gleam@map:get(Named, Name) of
{ok, Subjects} ->
Subjects;
{error, nil} ->
gleam@set:new()
end.
-spec delete_named(state(HCH, HCI), HCH) -> state(HCH, HCI).
delete_named(State, Name) ->
Other_named = gleam@map:delete(erlang:element(5, State), Name),
Other_subjects = gleam@map:fold(
Other_named,
gleam@set:new(),
fun(All_subjects, _, Subjects) ->
gleam@set:union(All_subjects, Subjects)
end
),
Subjects@1 = get_group(erlang:element(5, State), Name),
Subjects_to_keep = begin
_pipe = gleam@set:intersection(Subjects@1, Other_subjects),
gleam@set:to_list(_pipe)
end,
Subjects_to_delete = begin
_pipe@1 = gleam@set:drop(Subjects@1, Subjects_to_keep),
gleam@set:to_list(_pipe@1)
end,
Pids_to_delete = begin
_pipe@2 = Subjects_to_delete,
gleam@list:map(
_pipe@2,
fun(Subject) -> gleam@erlang@process:subject_owner(Subject) end
)
end,
Monitors = begin
_pipe@3 = erlang:element(3, State),
_pipe@4 = gleam@map:take(_pipe@3, Pids_to_delete),
gleam@map:values(_pipe@4)
end,
gleam@list:each(Monitors, fun gleam_erlang_ffi:demonitor/1),
Index = gleam@map:drop(erlang:element(3, State), Pids_to_delete),
Group = gleam@set:drop(erlang:element(4, State), Subjects_to_delete),
Named = gleam@map:delete(erlang:element(5, State), Name),
erlang:setelement(
5,
erlang:setelement(4, erlang:setelement(3, State, Index), Group),
Named
).
-spec receive_process_down(
gleam@erlang@process:selector(action(HDI, HDJ)),
gleam@erlang@process:process_monitor(),
gleam@erlang@process:subject(HDJ)
) -> gleam@erlang@process:selector(action(HDI, HDJ)).
receive_process_down(Selector, Monitor, Subject) ->
Handle = fun(_) -> {demonitor, Subject} end,
gleam@erlang@process:selecting_process_down(Selector, Monitor, Handle).
-spec insert(state(HBT, HBU), gleam@erlang@process:subject(HBU)) -> state(HBT, HBU).
insert(State, Subject) ->
Pid = gleam@erlang@process:subject_owner(Subject),
case gleam@map:get(erlang:element(3, State), Pid) of
{ok, Monitor} ->
Group = gleam@set:insert(erlang:element(4, State), Subject),
Selector = receive_process_down(
erlang:element(6, State),
Monitor,
Subject
),
erlang:setelement(6, erlang:setelement(4, State, Group), Selector);
{error, nil} ->
Monitor@1 = gleam@erlang@process:monitor_process(Pid),
Index = gleam@map:insert(erlang:element(3, State), Pid, Monitor@1),
Group@1 = gleam@set:insert(erlang:element(4, State), Subject),
Selector@1 = receive_process_down(
erlang:element(6, State),
Monitor@1,
Subject
),
erlang:setelement(
6,
erlang:setelement(
4,
erlang:setelement(3, State, Index),
Group@1
),
Selector@1
)
end.
-spec insert_as(state(HCA, HCB), gleam@erlang@process:subject(HCB), HCA) -> state(HCA, HCB).
insert_as(State, Subject, Name) ->
Subjects = begin
_pipe = erlang:element(5, State),
_pipe@1 = get_group(_pipe, Name),
gleam@set:insert(_pipe@1, Subject)
end,
Named = gleam@map:insert(erlang:element(5, State), Name, Subjects),
_pipe@2 = erlang:setelement(5, State, Named),
insert(_pipe@2, Subject).
-spec rebuild_process_down_selectors(state(HDC, HDD)) -> state(HDC, HDD).
rebuild_process_down_selectors(State) ->
Self = gleam@erlang@process:new_subject(),
Subjects = gleam@set:to_list(erlang:element(4, State)),
Selector@1 = begin
_pipe = gleam_erlang_ffi:new_selector(),
_pipe@1 = gleam@erlang@process:selecting(
_pipe,
Self,
fun gleam@function:identity/1
),
gleam@list:fold(
Subjects,
_pipe@1,
fun(Selector, Subject) ->
Pid = gleam@erlang@process:subject_owner(Subject),
case gleam@map:get(erlang:element(3, State), Pid) of
{ok, Monitor} ->
receive_process_down(Selector, Monitor, Subject);
{error, nil} ->
Selector
end
end
)
end,
erlang:setelement(6, erlang:setelement(2, State, Self), Selector@1).
-spec handle_message(action(HBM, HBN), state(HBM, HBN)) -> gleam@otp@actor:next(action(HBM, HBN), state(HBM, HBN)).
handle_message(Message, State) ->
case Message of
{all, Client} ->
Subjects = gleam@set:to_list(erlang:element(4, State)),
gleam@erlang@process:send(Client, Subjects),
gleam@otp@actor:continue(State);
{lookup, Client@1, Name} ->
Subjects@1 = begin
_pipe = get_group(erlang:element(5, State), Name),
gleam@set:to_list(_pipe)
end,
gleam@erlang@process:send(Client@1, Subjects@1),
gleam@otp@actor:continue(State);
{register, Subject} ->
State@1 = insert(State, Subject),
_pipe@1 = gleam@otp@actor:continue(State@1),
gleam@otp@actor:with_selector(_pipe@1, erlang:element(6, State@1));
{register_as, Subject@1, Name@1} ->
State@2 = insert_as(State, Subject@1, Name@1),
_pipe@2 = gleam@otp@actor:continue(State@2),
gleam@otp@actor:with_selector(_pipe@2, erlang:element(6, State@2));
{deregister, Name@2} ->
State@3 = delete_named(State, Name@2),
gleam@erlang@process:send(
erlang:element(2, State@3),
rebuild_selector
),
gleam@otp@actor:continue(State@3);
{demonitor, Subject@2} ->
State@4 = demonitor_subject(State, Subject@2),
gleam@erlang@process:send(
erlang:element(2, State@4),
rebuild_selector
),
gleam@otp@actor:continue(State@4);
rebuild_selector ->
State@5 = rebuild_process_down_selectors(State),
_pipe@3 = gleam@otp@actor:continue(State@5),
gleam@otp@actor:with_selector(_pipe@3, erlang:element(6, State@5));
{stop, Client@2} ->
gleam@erlang@process:send(Client@2, normal),
{stop, normal}
end.
-spec start() -> {ok, gleam@erlang@process:subject(action(any(), any()))} |
{error, gleam@otp@actor:start_error()}.
start() ->
gleam@otp@actor:start_spec(
{spec, fun handle_init/0, 10, fun handle_message/2}
).