Skip to content

Instantly share code, notes, and snippets.

@jan-g
Last active March 1, 2017 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jan-g/82e0c86c4accd722de30a638f56f8e3d to your computer and use it in GitHub Desktop.
Save jan-g/82e0c86c4accd722de30a638f56f8e3d to your computer and use it in GitHub Desktop.
"Priority" mailbox implementation (from Seven Chapters and Matt's Trousers in Some Weeks)
defmodule MyPriority do
# Despite racking up some other messages first,
# the initial loop only picks the "go" message
def loop do
IO.puts "in main loop"
receive do
{:go} ->
IO.puts "going"
loop2
end
end
def loop2 do
IO.puts "in secondary loop"
receive do
{a} ->
IO.puts "got #{a}"
loop2
end
end
def run do
IO.puts "running"
pid = spawn(MyPriority, :loop, [])
send pid, {:one}
send pid, {:two}
send pid, {:three}
send pid, {:go}
send pid, {:four}
end
# We can use this for a priority queue
def priority_loop do
receive do
{:priority, f} ->
apply(f, [:priority, :priority])
priority_loop
after
0 ->
receive do
{x, f} ->
apply(f, [x, :other])
priority_loop
end
end
end
# Here's a function that takes some time to run
def slow_function(p, from) do
IO.puts "in slow #{p} function called from #{from} loop"
:timer.sleep(:timer.seconds(1))
IO.puts "exiting slow #{p} function"
end
def run_p do
pid = spawn(MyPriority, :priority_loop, [])
send pid, {:normal, &slow_function/2}
:timer.sleep(2)
send pid, {:normal, &slow_function/2}
send pid, {:priority, &slow_function/2}
send pid, {:normal, &slow_function/2}
send pid, {:priority, &slow_function/2}
IO.puts "Everything queued for priority mailbox saving the last messages"
:timer.sleep(:timer.seconds(7))
IO.puts "Queueing final messages"
send pid, {:priority, &slow_function/2}
send pid, {:normal, &slow_function/2}
end
end
% iex
Erlang/OTP 18 [erts-7.3.1.2] [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false]
Interactive Elixir (1.2.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c("priority.ex")
hello.ex:1: warning: redefining module MyPriority
[MyPriority]
iex(2)> MyPriority.run
running
in main loop
going
in secondary loop
got one
{:four} <- return value from run/0
in secondary loop
got two
in secondary loop
got three
in secondary loop
got four
in secondary loop
iex(3)> MyPriority.run_p
in slow normal function called from other loop
Everything queued for priority mailbox saving the last messages
exiting slow normal function
in slow priority function called from priority loop
exiting slow priority function
in slow priority function called from priority loop
exiting slow priority function
in slow normal function called from other loop
exiting slow normal function
in slow normal function called from other loop
exiting slow normal function
Queueing final messages
in slow priority function called from other loop
{:normal, #Function<6.115860663/2 in MyPriority.run_p/0>} <- return value from run_p/0
exiting slow priority function
in slow normal function called from other loop
exiting slow normal function
iex(4)>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment