Current section

Files

Jump to
chip src chip.erl
Raw

src/chip.erl

-module(chip).
-compile([no_auto_import, nowarn_unused_vars]).
-export([all/1, lookup/2, register/2, register_as/3, deregister/2, stop/1, start/0]).
-export_type([action/2, state/2]).
-opaque action(GVS, GVT) :: {all,
gleam@erlang@process:subject(list(gleam@erlang@process:subject(GVT)))} |
{lookup,
gleam@erlang@process:subject(list(gleam@erlang@process:subject(GVT))),
GVS} |
{register, gleam@erlang@process:subject(GVT)} |
{register_as, gleam@erlang@process:subject(GVT), GVS} |
{deregister, GVS} |
{demonitor, gleam@erlang@process:subject(GVT)} |
{stop, gleam@erlang@process:subject(gleam@erlang@process:exit_reason())}.
-type state(GVU, GVV) :: {state,
gleam@map:map_(gleam@erlang@process:subject(GVU), gleam@erlang@process:process_monitor()),
gleam@map:map_(GVV, gleam@set:set(gleam@erlang@process:subject(GVU))),
gleam@erlang@process:selector(action(GVV, GVU))}.
-spec all(gleam@erlang@process:subject(action(any(), GWE))) -> list(gleam@erlang@process:subject(GWE)).
all(Registry) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {all, _capture} end,
100
).
-spec lookup(gleam@erlang@process:subject(action(GWK, GWL)), GWK) -> list(gleam@erlang@process:subject(GWL)).
lookup(Registry, Name) ->
gleam@erlang@process:call(
Registry,
fun(_capture) -> {lookup, _capture, Name} end,
100
).
-spec register(
gleam@erlang@process:subject(action(any(), GWS)),
fun(() -> {ok, gleam@erlang@process:subject(GWS)} |
{error, gleam@otp@actor:start_error()})
) -> {ok, gleam@erlang@process:subject(GWS)} |
{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(GXC, GXD)),
GXC,
fun(() -> {ok, gleam@erlang@process:subject(GXD)} |
{error, gleam@otp@actor:start_error()})
) -> {ok, gleam@erlang@process:subject(GXD)} |
{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(GXN, any())), GXN) -> 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 demonitor_subject(state(GYY, GYZ), gleam@erlang@process:subject(GYY)) -> state(GYY, GYZ).
demonitor_subject(State, Subject) ->
case gleam@map:get(erlang:element(2, State), Subject) of
{ok, Monitor} ->
gleam_erlang_ffi:demonitor(Monitor),
Group = gleam@map:delete(erlang:element(2, State), Subject),
Named = gleam@map:map_values(
erlang:element(3, State),
fun(_, Subjects) -> gleam@set:delete(Subjects, Subject) end
),
State@1 = erlang:setelement(
3,
erlang:setelement(2, State, Group),
Named
),
State@1;
{error, nil} ->
State
end.
-spec get_name(
gleam@map:map_(GZF, gleam@set:set(gleam@erlang@process:subject(GZG))),
GZF
) -> gleam@set:set(gleam@erlang@process:subject(GZG)).
get_name(Named, Name) ->
case gleam@map:get(Named, Name) of
{ok, Subjects} ->
Subjects;
{error, nil} ->
gleam@set:new()
end.
-spec delete_named(state(GYS, GYT), GYT) -> state(GYS, GYT).
delete_named(State, Name) ->
Other_named = gleam@map:delete(erlang:element(3, 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_name(erlang:element(3, 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,
Monitors = begin
_pipe@2 = erlang:element(2, State),
_pipe@3 = gleam@map:take(_pipe@2, Subjects_to_delete),
gleam@map:values(_pipe@3)
end,
gleam@list:each(Monitors, fun gleam_erlang_ffi:demonitor/1),
Group = gleam@map:drop(erlang:element(2, State), Subjects_to_delete),
Named = gleam@map:delete(erlang:element(3, State), Name),
erlang:setelement(3, erlang:setelement(2, State, Group), Named).
-spec capture_process_down(
gleam@erlang@process:selector(action(GZN, GZO)),
gleam@erlang@process:process_monitor(),
gleam@erlang@process:subject(GZO)
) -> gleam@erlang@process:selector(action(GZN, GZO)).
capture_process_down(Selector, Monitor, Subject) ->
Handle = fun(_) -> {demonitor, Subject} end,
gleam@erlang@process:selecting_process_down(Selector, Monitor, Handle).
-spec insert(
state(GYE, GYF),
gleam@erlang@process:subject(GYE),
gleam@erlang@process:process_monitor()
) -> state(GYE, GYF).
insert(State, Subject, Monitor) ->
Group = gleam@map:insert(erlang:element(2, State), Subject, Monitor),
Selector = capture_process_down(erlang:element(4, State), Monitor, Subject),
erlang:setelement(4, erlang:setelement(2, State, Group), Selector).
-spec insert_as(
state(GYL, GYM),
gleam@erlang@process:subject(GYL),
gleam@erlang@process:process_monitor(),
GYM
) -> state(GYL, GYM).
insert_as(State, Subject, Monitor, Name) ->
Subjects = begin
_pipe = erlang:element(3, State),
_pipe@1 = get_name(_pipe, Name),
gleam@set:insert(_pipe@1, Subject)
end,
Named = gleam@map:insert(erlang:element(3, State), Name, Subjects),
_pipe@2 = erlang:setelement(3, State, Named),
insert(_pipe@2, Subject, Monitor).
-spec handle_message(action(GXX, GXY), state(GXY, GXX)) -> gleam@otp@actor:next(action(GXX, GXY), state(GXY, GXX)).
handle_message(Message, State) ->
case Message of
{all, Client} ->
Subjects = gleam@map:keys(erlang:element(2, State)),
gleam@erlang@process:send(Client, Subjects),
gleam@otp@actor:continue(State);
{lookup, Client@1, Name} ->
Subjects@1 = begin
_pipe = erlang:element(3, State),
_pipe@1 = get_name(_pipe, Name),
gleam@set:to_list(_pipe@1)
end,
gleam@erlang@process:send(Client@1, Subjects@1),
gleam@otp@actor:continue(State);
{register, Subject} ->
Monitor = begin
_pipe@2 = Subject,
_pipe@3 = gleam@erlang@process:subject_owner(_pipe@2),
gleam@erlang@process:monitor_process(_pipe@3)
end,
State@1 = insert(State, Subject, Monitor),
_pipe@4 = gleam@otp@actor:continue(State@1),
gleam@otp@actor:with_selector(_pipe@4, erlang:element(4, State@1));
{register_as, Subject@1, Name@1} ->
Monitor@1 = begin
_pipe@5 = Subject@1,
_pipe@6 = gleam@erlang@process:subject_owner(_pipe@5),
gleam@erlang@process:monitor_process(_pipe@6)
end,
State@2 = insert_as(State, Subject@1, Monitor@1, Name@1),
_pipe@7 = gleam@otp@actor:continue(State@2),
gleam@otp@actor:with_selector(_pipe@7, erlang:element(4, State@2));
{deregister, Name@2} ->
State@3 = begin
_pipe@8 = State,
delete_named(_pipe@8, Name@2)
end,
_pipe@9 = gleam@otp@actor:continue(State@3),
gleam@otp@actor:with_selector(_pipe@9, erlang:element(4, State@3));
{demonitor, Subject@2} ->
State@4 = begin
_pipe@10 = State,
demonitor_subject(_pipe@10, Subject@2)
end,
_pipe@11 = gleam@otp@actor:continue(State@4),
gleam@otp@actor:with_selector(_pipe@11, erlang:element(4, State@4));
{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(
{state,
gleam@map:new(),
gleam@map:new(),
gleam_erlang_ffi:new_selector()},
fun handle_message/2
).