Skip to content

Instantly share code, notes, and snippets.

@odo
Created April 27, 2017 08:32
Show Gist options
  • Save odo/48abcd6a57afc9ccecc816692aa2f3d9 to your computer and use it in GitHub Desktop.
Save odo/48abcd6a57afc9ccecc816692aa2f3d9 to your computer and use it in GitHub Desktop.
An elixir server holding a capped/limited buffer
defmodule LimitedBuffer do
use GenServer
# Client
def start_link(size, name \\ nil) do
GenServer.start_link(__MODULE__, [size, name])
end
def push(server, item) do
GenServer.cast(server, {:push, item})
end
# for testing
def push_sync(server, item) do
GenServer.call(server, {:push, item})
end
def elements(pid) do
GenServer.call(pid, :elements)
end
# Server (callbacks)
def init([size, name]) do
if name, do: Process.register(self(), name)
{:ok, %{queue: :queue.new(), size: size}}
end
def handle_call(:elements, _from, state) do
elements = :queue.to_list(state.queue)
{:reply, elements, state}
end
def handle_call({:push, item}, _from, state) do
next_state = state |> push_internal(item)
{:reply, :ok, next_state}
end
def handle_cast({:push, item}, state) do
next_state = state |> push_internal(item)
{:noreply, next_state}
end
defp push_internal(state = %{queue: queue, size: size}, item) do
queue_add = :queue.in(item, queue)
oversize = size + 1
next_queue =
case :queue.len(queue_add) do
^oversize ->
{_, queue_trim} = :queue.out(queue_add)
queue_trim
_ ->
queue_add
end
%{state | queue: next_queue}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment