Current section

Files

Jump to
puddle src puddle.erl
Raw

src/puddle.erl

-module(puddle).
-compile([no_auto_import, nowarn_unused_vars]).
-export([apply/4, start/2]).
-export_type([bookkeeping_message/2, usage_message/2]).
-opaque bookkeeping_message(GVS, GVT) :: shutdown |
{check_in, gleam@erlang@process:subject(usage_message(GVS, GVT))} |
{check_out,
gleam@erlang@process:subject({ok,
gleam@erlang@process:subject(usage_message(GVS, GVT))} |
{error, nil})}.
-opaque usage_message(GVU, GVV) :: {usage_message,
fun((GVU) -> GVV),
gleam@erlang@process:subject({ok, GVV} | {error, nil})}.
-spec check_out(
gleam@erlang@process:subject(bookkeeping_message(GWS, GWT)),
integer()
) -> {ok, gleam@erlang@process:subject(usage_message(GWS, GWT))} | {error, nil}.
check_out(Manager, Timeout) ->
gleam@erlang@process:call(
Manager,
fun(Field@0) -> {check_out, Field@0} end,
Timeout
).
-spec utilize(
gleam@erlang@process:subject(usage_message(GWY, GWZ)),
fun((GWY) -> GWZ),
gleam@erlang@process:subject({ok, GWZ} | {error, nil})
) -> nil.
utilize(Subject, Fun, Mine) ->
gleam@erlang@process:send(Subject, {usage_message, Fun, Mine}).
-spec check_in(
gleam@erlang@process:subject(bookkeeping_message(GXH, GXI)),
gleam@erlang@process:subject(usage_message(GXH, GXI))
) -> nil.
check_in(Manager, Subject) ->
gleam@erlang@process:send(Manager, {check_in, Subject}).
-spec apply(
gleam@erlang@process:subject(bookkeeping_message(GWL, GWM)),
fun((GWL) -> GWM),
integer(),
fun(({ok, GWM} | {error, nil}) -> {ok, GZI} | {error, nil})
) -> {ok, GZI} | {error, nil}.
apply(Manager, Fun, Timeout, Rest) ->
gleam@result:then(
check_out(Manager, Timeout),
fun(Subject) ->
Mine = gleam@erlang@process:new_subject(),
utilize(Subject, Fun, Mine),
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:selecting(_pipe, Mine, fun(R) -> R end)
end,
Result = begin
_pipe@1 = gleam_erlang_ffi:select(Selector, Timeout),
gleam@result:flatten(_pipe@1)
end,
check_in(Manager, Subject),
Rest(Result)
end
).
-spec handle_bookkeeping_message(
bookkeeping_message(GXY, GXZ),
list({gleam@erlang@process:pid_(),
gleam@erlang@process:subject(usage_message(GXY, GXZ))})
) -> gleam@otp@actor:next(any(), list({gleam@erlang@process:pid_(),
gleam@erlang@process:subject(usage_message(GXY, GXZ))})).
handle_bookkeeping_message(Msg, Puddle) ->
case Msg of
shutdown ->
gleam@list:each(
Puddle,
fun(Item) ->
gleam@erlang@process:kill(erlang:element(1, Item))
end
),
{stop, normal};
{check_in, Subject} ->
Pid = gleam@erlang@process:subject_owner(Subject),
gleam@otp@actor:continue(gleam@list:prepend(Puddle, {Pid, Subject}));
{check_out, Client} ->
case Puddle of
[] ->
gleam@otp@actor:send(Client, {error, nil}),
gleam@otp@actor:continue(Puddle);
[{_, Chosen} | New_puddle] ->
gleam@otp@actor:send(Client, {ok, Chosen}),
gleam@otp@actor:continue(New_puddle)
end
end.
-spec handle_usage_message(usage_message(GYF, any()), GYF) -> gleam@otp@actor:next(any(), GYF).
handle_usage_message(Msg, Resource) ->
case Msg of
{usage_message, Fun, Client} ->
Result = Fun(Resource),
gleam@otp@actor:send(Client, {ok, Result}),
gleam@otp@actor:continue(Resource)
end.
-spec new(integer(), fun(() -> {ok, GXQ} | {error, nil})) -> {ok,
list({gleam@erlang@process:pid_(),
gleam@erlang@process:subject(usage_message(GXQ, any()))})} |
{error, nil}.
new(Size, New_resource) ->
_pipe = gleam@list:repeat(<<""/utf8>>, Size),
gleam@list:try_map(_pipe, fun(_) -> case New_resource() of
{ok, Initial_state} ->
_pipe@1 = gleam@otp@actor:start(
Initial_state,
fun handle_usage_message/2
),
_pipe@2 = gleam@result:map(
_pipe@1,
fun(Subject) ->
Pid = gleam@erlang@process:subject_owner(Subject),
{Pid, Subject}
end
),
gleam@result:nil_error(_pipe@2);
{error, nil} ->
{error, nil}
end end).
-spec start(integer(), fun(() -> {ok, GWC} | {error, nil})) -> {ok,
gleam@erlang@process:subject(bookkeeping_message(GWC, any()))} |
{error, gleam@otp@actor:start_error()}.
start(Size, New_resource) ->
gleam@result:then(
begin
_pipe = new(Size, New_resource),
gleam@result:map_error(
_pipe,
fun(_) ->
{init_failed,
{abnormal, <<"Failed to create new resource"/utf8>>}}
end
)
end,
fun(Puddle) ->
gleam@otp@actor:start(Puddle, fun handle_bookkeeping_message/2)
end
).