-module(puddle). -compile([no_auto_import, nowarn_unused_vars]). -export([start_manager/2]). -export_type([usage_message/2, bookkeeping_message/2]). -type usage_message(GVS, GVT) :: {usage_message, fun((GVS) -> GVT), gleam@erlang@process:subject({ok, GVT} | {error, nil})}. -type bookkeeping_message(GVU, GVV) :: shutdown | {put_back, gleam@erlang@process:subject(usage_message(GVU, GVV))} | {checkout, gleam@erlang@process:subject({ok, gleam@erlang@process:subject(usage_message(GVU, GVV))} | {error, nil})}. -spec handle_bookkeeping_message( bookkeeping_message(GWT, GWU), list({gleam@erlang@process:pid_(), gleam@erlang@process:subject(usage_message(GWT, GWU))}) ) -> gleam@otp@actor:next(any(), list({gleam@erlang@process:pid_(), gleam@erlang@process:subject(usage_message(GWT, GWU))})). 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}; {put_back, Subject} -> Pid = gleam@erlang@process:subject_owner(Subject), gleam@otp@actor:continue(gleam@list:prepend(Puddle, {Pid, Subject})); {checkout, 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(GXA, any()), GXA) -> gleam@otp@actor:next(any(), GXA). handle_usage_message(Msg, Resource) -> case Msg of {usage_message, Func, Client} -> Result = Func(Resource), gleam@otp@actor:send(Client, {ok, Result}), gleam@otp@actor:continue(Resource) end. -spec new(integer(), fun(() -> {ok, GWL} | {error, nil})) -> {ok, list({gleam@erlang@process:pid_(), gleam@erlang@process:subject(usage_message(GWL, 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_manager(integer(), fun(() -> {ok, GWC} | {error, nil})) -> {ok, gleam@erlang@process:subject(bookkeeping_message(GWC, any()))} | {error, nil}. start_manager(Size, New_resource) -> gleam@result:then( new(Size, New_resource), fun(Puddle) -> _pipe = gleam@otp@actor:start( Puddle, fun handle_bookkeeping_message/2 ), gleam@result:nil_error(_pipe) end ).