-module(chip). -compile([no_auto_import, nowarn_unused_vars]). -export([register/3, unregister/2, find/2, start/0]). -export_type([message/2, record/1, errors/0]). -opaque message(GVS, GVT) :: {register, GVS, gleam@erlang@process:subject(GVT)} | {unregister, GVS} | {find, gleam@erlang@process:subject({ok, gleam@erlang@process:subject(GVT)} | {error, errors()}), GVS}. -type record(GVU) :: {record, gleam@erlang@process:subject(GVU), gleam@erlang@process:process_monitor()}. -type errors() :: not_found. -spec register( gleam@erlang@process:subject(message(GWD, GWE)), GWD, gleam@erlang@process:subject(GWE) ) -> nil. register(Registry, Name, Subject) -> gleam@erlang@process:send(Registry, {register, Name, Subject}). -spec unregister(gleam@erlang@process:subject(message(GWH, any())), GWH) -> nil. unregister(Registry, Name) -> gleam@erlang@process:send(Registry, {unregister, Name}). -spec find(gleam@erlang@process:subject(message(GWJ, GWK)), GWJ) -> {ok, gleam@erlang@process:subject(GWK)} | {error, errors()}. find(Registry, Name) -> gleam@erlang@process:call( Registry, fun(Self) -> {find, Self, Name} end, 100 ). -spec handle_message(message(GWO, GWP), gleam@map:map_(GWO, record(GWP))) -> gleam@otp@actor:next(message(GWO, any()), gleam@map:map_(GWO, record(GWP))). handle_message(Message, State) -> case Message of {register, Name, Subject} -> Monitor = begin _pipe = Subject, _pipe@1 = gleam@erlang@process:subject_owner(_pipe), gleam@erlang@process:monitor_process(_pipe@1) end, State@1 = gleam@map:insert(State, Name, {record, Subject, Monitor}), Handle_down = fun(_) -> {unregister, Name} end, Handle_process_down = begin _pipe@2 = gleam_erlang_ffi:new_selector(), gleam@erlang@process:selecting_process_down( _pipe@2, Monitor, Handle_down ) end, _pipe@3 = gleam@otp@actor:continue(State@1), gleam@otp@actor:with_selector(_pipe@3, Handle_process_down); {unregister, Name@1} -> case gleam@map:get(State, Name@1) of {ok, {record, _, Monitor@1}} -> gleam_erlang_ffi:demonitor(Monitor@1), State@2 = gleam@map:delete(State, Name@1), gleam@otp@actor:continue(State@2); {error, nil} -> gleam@otp@actor:continue(State) end; {find, Client, Name@2} -> case gleam@map:get(State, Name@2) of {ok, {record, Subject@1, _}} -> gleam@erlang@process:send(Client, {ok, Subject@1}), gleam@otp@actor:continue(State); {error, nil} -> gleam@erlang@process:send(Client, {error, not_found}), gleam@otp@actor:continue(State) end end. -spec start() -> {ok, gleam@erlang@process:subject(message(any(), any()))} | {error, gleam@otp@actor:start_error()}. start() -> gleam@otp@actor:start(gleam@map:new(), fun handle_message/2).