Current section
Files
Jump to
Current section
Files
src/gleam@otp@process.erl
-module(gleam@otp@process).
-compile(no_auto_import).
-export([new_reference/0, self/0, system_receiver/0, new_channel/0, new_bare_sender/1, close_channels/1, pid/1, pid_from_dynamic/1, send/2, null_sender/1, monitor_process/1, monitor_port/1, receive_forever/1, flush/1, merge_receiver/2, bare_message_receiver/0, debug_state/1, is_alive/1, kill/1, send_exit/2, start/1, start_unlinked/1, 'receive'/2, map_receiver/2, map_sender/2, try_call/3, call/3, message_queue_size/1, trap_exits/0, stop_trapping_exits/0, send_after/3, cancel_timer/1, link/1, unlink/1, untyped_send/2]).
-export_type([pid_/0, reference_/0, sender/1, receiver/1, process_monitor_flag/0, port_monitor_flag/0, process_down/0, port_down/0, exit/0, exit_reason/0, mode/0, debug_option/0, debug_state/0, status_info/0, system_message/0, kill_flag/0, call_error/1, message_queue_len_flag/0, timer/0, cancelled/0]).
-type pid_() :: any().
-type reference_() :: any().
-opaque sender(EKU) :: {sender,
pid_(),
gleam@option:option(fun((EKU) -> gleam@dynamic:dynamic()))}.
-type receiver(Msg) :: any() | {gleam_phantom, Msg}.
-type process_monitor_flag() :: process.
-type port_monitor_flag() :: port.
-type process_down() :: {process_down, pid_(), gleam@dynamic:dynamic()}.
-type port_down() :: {port_down,
gleam@otp@port:port_(),
gleam@dynamic:dynamic()}.
-type exit() :: {exit, pid_(), gleam@dynamic:dynamic()}.
-type exit_reason() :: normal | shutdown | {abnormal, gleam@dynamic:dynamic()}.
-type mode() :: running | suspended.
-type debug_option() :: no_debug.
-type debug_state() :: any().
-type status_info() :: {status_info,
gleam@erlang@atom:atom_(),
pid_(),
mode(),
debug_state(),
gleam@dynamic:dynamic()}.
-type system_message() :: {get_status, sender(status_info())} |
{suspend, sender(nil)} |
{resume, sender(nil)} |
{get_state, sender(gleam@dynamic:dynamic())}.
-type kill_flag() :: kill.
-type call_error(EKW) :: {callee_down, gleam@dynamic:dynamic()} |
call_timeout |
{gleam_phantom, EKW}.
-type message_queue_len_flag() :: message_queue_len.
-type timer() :: any().
-type cancelled() :: timer_not_found | {cancelled, integer()}.
-spec new_reference() -> reference_().
new_reference() ->
erlang:make_ref().
-spec self() -> pid_().
self() ->
erlang:self().
-spec system_receiver() -> receiver(system_message()).
system_receiver() ->
gleam_otp_external:system_receiver().
-spec new_channel() -> {sender(ELD), receiver(ELD)}.
new_channel() ->
Reference = erlang:make_ref(),
Sender = begin
_pipe = erlang:self(),
_pipe@1 = new_bare_sender(_pipe),
map_sender(_pipe@1, fun(Msg) -> {Reference, Msg} end)
end,
Receiver = gleam_otp_external:new_receiver(Reference),
{Sender, Receiver}.
-spec new_bare_sender(pid_()) -> sender(any()).
new_bare_sender(Pid) ->
Prepare = fun(Msg) -> gleam@dynamic:from(Msg) end,
{sender, Pid, {some, Prepare}}.
-spec close_channels(receiver(any())) -> nil.
close_channels(A) ->
gleam_otp_external:close_channels(A).
-spec pid(sender(any())) -> pid_().
pid(Sender) ->
erlang:element(2, Sender).
-spec pid_from_dynamic(gleam@dynamic:dynamic()) -> {ok, pid_()} |
{error, list(gleam@dynamic:decode_error())}.
pid_from_dynamic(A) ->
gleam_otp_external:pid_from_dynamic(A).
-spec send(sender(ELP), ELP) -> sender(ELP).
send(Sender, Message) ->
case erlang:element(3, Sender) of
{some, Prepare} ->
_pipe = Message,
_pipe@1 = Prepare(_pipe),
erlang:send(erlang:element(2, Sender), _pipe@1),
Sender;
none ->
Sender
end.
-spec null_sender(pid_()) -> sender(any()).
null_sender(Pid) ->
{sender, Pid, none}.
-spec monitor_process(pid_()) -> receiver(process_down()).
monitor_process(Pid) ->
Reference = erlang:monitor(process, Pid),
gleam_otp_external:new_receiver({process, Reference}).
-spec monitor_port(gleam@otp@port:port_()) -> receiver(port_down()).
monitor_port(Port) ->
Reference = erlang:monitor(port, Port),
gleam_otp_external:new_receiver({port, Reference}).
-spec receive_forever(receiver(ELW)) -> ELW.
receive_forever(A) ->
gleam_otp_external:run_receiver_forever(A).
-spec flush(receiver(any())) -> integer().
flush(A) ->
gleam_otp_external:flush_receiver(A).
-spec merge_receiver(receiver(EMA), receiver(EMA)) -> receiver(EMA).
merge_receiver(A, B) ->
gleam_otp_external:merge_receiver(A, B).
-spec bare_message_receiver() -> receiver(gleam@dynamic:dynamic()).
bare_message_receiver() ->
gleam_otp_external:bare_message_receiver().
-spec debug_state(list(debug_option())) -> debug_state().
debug_state(A) ->
sys:debug_options(A).
-spec is_alive(pid_()) -> boolean().
is_alive(A) ->
erlang:is_process_alive(A).
-spec kill(pid_()) -> nil.
kill(Pid) ->
erlang:exit(Pid, kill),
nil.
-spec send_exit(pid_(), any()) -> nil.
send_exit(Pid, Reason) ->
erlang:exit(Pid, Reason),
nil.
-spec start(fun(() -> any())) -> pid_().
start(A) ->
erlang:spawn_link(A).
-spec start_unlinked(fun(() -> any())) -> pid_().
start_unlinked(A) ->
erlang:spawn(A).
-spec 'receive'(receiver(EMO), integer()) -> {ok, EMO} | {error, nil}.
'receive'(A, B) ->
gleam_otp_external:run_receiver(A, B).
-spec map_receiver(receiver(EMU), fun((EMU) -> EMS)) -> receiver(EMS).
map_receiver(A, B) ->
gleam_otp_external:map_receiver(A, B).
-spec map_sender(sender(EMW), fun((EMY) -> EMW)) -> sender(EMY).
map_sender(Sender, Mapper) ->
Wrap = fun(_capture) -> gleam@function:compose(Mapper, _capture) end,
Prepare = gleam@option:map(erlang:element(3, Sender), Wrap),
{sender, erlang:element(2, Sender), Prepare}.
-spec try_call(sender(ENA), fun((sender(ENC)) -> ENA), integer()) -> {ok, ENC} |
{error, call_error(ENC)}.
try_call(Sender, Make_request, Timeout) ->
{Reply_sender, Reply_receiver} = new_channel(),
Monitor = monitor_process(pid(Sender)),
send(Sender, Make_request(Reply_sender)),
Receiver = begin
_pipe = Reply_receiver,
_pipe@1 = gleam_otp_external:map_receiver(_pipe, fun(A) -> {ok, A} end),
gleam_otp_external:merge_receiver(
_pipe@1,
gleam_otp_external:map_receiver(
Monitor,
fun(Down) -> {error, {callee_down, erlang:element(3, Down)}} end
)
)
end,
Res = gleam_otp_external:run_receiver(Receiver, Timeout),
gleam_otp_external:close_channels(Receiver),
case Res of
{error, nil} ->
{error, call_timeout};
{ok, Res@1} ->
Res@1
end.
-spec call(sender(ENH), fun((sender(ENJ)) -> ENH), integer()) -> ENJ.
call(Sender, Make_request, Timeout) ->
{ok, Resp@1} = case try_call(Sender, Make_request, Timeout) of
{ok, Resp} -> {ok, Resp};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam/otp/process"/utf8>>,
function => <<"call"/utf8>>,
line => 475})
end,
Resp@1.
-spec message_queue_size(pid_()) -> integer().
message_queue_size(Pid) ->
erlang:element(2, erlang:process_info(Pid, message_queue_len)).
-spec trap_exits() -> receiver(exit()).
trap_exits() ->
gleam_otp_external:trap_exits().
-spec stop_trapping_exits() -> nil.
stop_trapping_exits() ->
gleam_otp_external:stop_trapping_exits().
-spec send_after(sender(ENN), integer(), ENN) -> timer().
send_after(Sender, Delay, Message) ->
case erlang:element(3, Sender) of
{some, Prepare} ->
erlang:send_after(
Delay,
erlang:element(2, Sender),
Prepare(Message)
);
none ->
erlang:make_ref()
end.
-spec cancel_timer(timer()) -> cancelled().
cancel_timer(Timer) ->
case gleam@dynamic:int(erlang:cancel_timer(Timer)) of
{ok, I} ->
{cancelled, I};
{error, _@1} ->
timer_not_found
end.
-spec link(pid_()) -> nil.
link(Pid) ->
erlang:link(Pid),
nil.
-spec unlink(pid_()) -> nil.
unlink(Pid) ->
erlang:link(Pid),
nil.
-spec untyped_send(pid_(), ENP) -> ENP.
untyped_send(A, B) ->
erlang:send(A, B).