Current section
Files
Jump to
Current section
Files
lib/task_awaiter.ex
defmodule TaskAwaiter do
use GenServer
defstruct [:state, :condition_verifier, :result_acceptor, :awaiter_notifier]
# API
def start_link(initial_state, initializer, condition_verifier, result_acceptor, awaiter_notifier, gen_server_options \\ []) do
GenServer.start_link(__MODULE__, [initial_state, initializer, condition_verifier, result_acceptor, awaiter_notifier], gen_server_options)
end
def task_completed(server, result) do
server |> GenServer.cast({:accept_result, result})
end
# Callbacks
def init([initial_state, initializer, condition_verifier, result_acceptor, awaiter_notifier]) do
initial_state =
if initializer do
initializer.(initial_state)
else
initial_state
end
{:ok, %TaskAwaiter{state: initial_state, condition_verifier: condition_verifier, result_acceptor: result_acceptor, awaiter_notifier: awaiter_notifier}}
end
def handle_cast({:accept_result, result}, %TaskAwaiter{state: awaiter_state, result_acceptor: result_acceptor, condition_verifier: condition_verifier, awaiter_notifier: awaiter_notifier} = state) do
new_awaiter_state = awaiter_state |> result_acceptor.(result) |> coalesce(condition_verifier, awaiter_notifier)
{:noreply, %{state|state: new_awaiter_state}}
end
def handle_info({ref, _result} = msg, state) when ref |> is_reference() do
self() |> task_completed(msg)
{:noreply, state}
end
def handle_info(_, state) do
{:noreply, state}
end
# Helper functions
def coalesce(value, condition, transformation) do
if condition.(value) do
transformation.(value)
else
value
end
end
end