Skip to content

Instantly share code, notes, and snippets.

@sergio1990
Created July 6, 2016 14:35
Show Gist options
  • Save sergio1990/b8d0f2809259f88dd7d44b27d1f20385 to your computer and use it in GitHub Desktop.
Save sergio1990/b8d0f2809259f88dd7d44b27d1f20385 to your computer and use it in GitHub Desktop.
I tried to implement the basic functionality of GenServer by myself :-)
defmodule MyGenServer do
defmacro __using__(_options \\ :empty) do
quote do
def start_link(default_state) do
Task.start_link(fn -> loop(default_state) end)
end
def loop(state) do
receive do
{:call, options, caller} ->
{:reply, response, new_state} = __MODULE__.handle_call(options, state)
send caller, response
loop(new_state)
{:cast, options} ->
:timer.sleep(2000)
{:noreply, new_state} = __MODULE__.handle_cast(options, state)
loop(new_state)
end
end
def call(pid, options) do
send pid, {:call, options, self()}
receive do
server_response ->
server_response
end
end
def cast(pid, options) do
send pid, {:cast, options}
:ok
end
def handle_call(msg, state) do
{:bad_call, msg}
end
def handle_cast(msg, state) do
{:bad_cast, msg}
end
defoverridable [handle_call: 2, handle_cast: 2]
end
end
end
defmodule Mapper do
use MyGenServer
def handle_call({:get, key}, state) do
element = Map.get(state, key)
{:reply, element, state}
end
def handle_cast({:put, key, value}, state) do
new_state = Map.put(state, key, value)
{:noreply, new_state}
end
end
{:ok, mapper_pid} = Mapper.start_link(%{})
Mapper.cast mapper_pid, {:put, :test1, :value1}
IO.puts "Value for the key `:test1`:"
IO.puts Mapper.call mapper_pid, {:get, :test1}
IO.puts "Value for the key `:test2`:"
IO.puts Mapper.call mapper_pid, {:get, :test2}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment