Skip to content

Instantly share code, notes, and snippets.

@tiagopog
Last active April 11, 2019 06:15
Show Gist options
  • Save tiagopog/1a9a8223331781de1b2845c3b6ae4ca7 to your computer and use it in GitHub Desktop.
Save tiagopog/1a9a8223331781de1b2845c3b6ae4ca7 to your computer and use it in GitHub Desktop.
Elixir - Processes (spawn, send, receive, Async, Agent)
defmodule Account do
defstruct name: nil, amount: 0
def start(%Account{} = account) do
spawn fn -> run(account) end
end
defp run(account) do
account = receive do
{:debit, value} -> %{account | amount: account.amount - value}
{:credit, value} -> %{account | amount: account.amount + value}
{:show, caller} -> send(caller, account)
end
run(account)
end
end
# acc = Account.start(%Account{name: 'Tiago', amount: 100})
# send(acc, {:debit, 10})
# send(acc, {:show, self})
# receive do
# value -> value
# after 1_000 -> IO.puts "No message received"
# end
defmodule Account do
defstruct name: nil, amount: 0
def start(%Account{} = account) do
{:ok, pid} = Agent.start fn -> account end
pid
end
def credit(pid, value) do
Agent.update(pid, fn account ->
%{account | amount: account.amount + value}
end)
end
def debit(pid, value) do
Agent.update(pid, fn account ->
%{account | amount: account.amount - value}
end)
end
def show(pid) do
Agent.get(pid, fn account -> account end)
end
end
# acc = Account.start(%Account{name: 'Tiago', amount: 100})
# Account.debit(acc, 20)
# Account.credit(acc, 10)
# Account.show(acc)
defmodule AsyncTest do
@contents ["foo", "bar", "foobar"]
@output "async_test"
def run do
File.rm_rf!(@output)
File.mkdir_p!(@output)
@contents
|> Enum.with_index
|> Enum.map(&write_content_async(&1))
|> Enum.map(fn _ ->
receive do
:ok -> :ok
{:error, reason} -> IO.puts :stderr, "Error: #{reason}"
after 3000 ->
IO.puts :stderr, "Timeout"
end
end)
end
def write_content_async(params) do
caller = self()
spawn(fn ->
seconds = :rand.uniform(10) * 1000
:timer.sleep(seconds)
send(caller, write_content(params))
end)
end
def write_content({content, index})do
IO.puts "Write \"#{content}\" into a file"
File.write("#{@output}/test_#{index + 1}.txt", content)
end
end
defmodule AsyncTest2 do
@contents ["foo", "bar", "foobar"]
@output "async_test"
def run do
File.rm_rf!(@output)
File.mkdir_p!(@output)
@contents
|> Enum.with_index
|> Enum.map(&Task.async(fn ->
write_content(&1)
end))
|> Enum.map(&Task.await/1)
end
def write_content({content, index}) do
seconds = :rand.uniform(5) * 1000
:timer.sleep(seconds)
IO.puts "Write \"#{content}\" into a file"
File.write("#{@output}/test_#{index + 1}.txt", content)
end
end
defmodule Person do
@default_attrs %{name: nil}
def new(attrs) do
spawn fn ->
Map.merge(@default_attrs, attrs) |> run
end
end
defp run(attrs) do
receive do
:name -> IO.puts(attrs[:name])
{:set_name, name} -> attrs = Map.merge(attrs, %{name: name})
end
run(attrs)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment