cbuf v0.7.1 Cbuf.ETS
Cbuf.ETS
implements the Cbuf
behaviour with an ETS table as its implementation.
For examples of typical use, see the documentation for new/1
, insert/2
, peek/1
, and delete/1
.
Each new buffer creates and owns a new ETS table.
Operations that must interact with the actual data of the buffer
(new/1
, insert/2
, peek/1
, pop/1
, delete/1
, to_list/1
, member?/2
),
perform as well as ETS does.
Use this module if you have tried Cbuf.Map
with a GenServer and benchmarked it against this one to determine that
this one is faster for your application. I recommend defaulting to Cbuf.Map
.
This module is not currently designed or tested for parallel writes, and so I also recommend using it
as part of a GenServer. Crucially, the start
and current
pointers are stored on the struct itself,
rather than somewhere in ETS, so they are completely uncoordinated with the backing implementation and require
updates to be serialized.
This may change at some point if I can determine that this is a beneficial use case and can be implemented in
a way that preserves the existing API.
Note that this module is a superset of the Cbuf
behaviour, implementing one additional function, destroy/1
,
to destroy the buffer’s backing ETS table. See the function documentation for more details.
Link to this section Summary
Functions
Returns the count of the non-empty values in the buffer
Return a new buffer with the oldest item in the buffer removed
Destroy the backing ETS table of a buffer. This function exists if you wish to manually dispose of the ETS table that backs the buffer. The other option is to destroy the process in which the buffer was created, as the ETS table will be disposed of when its parent process dies. See http://erlang.org/doc/man/ets.html for more information about the behavior of ETS tables
Whether or not the buffer is empty.
This value corresponds to when the buffer has a count
of zero, not its size
Insert a value into a circular buffer. Values are inserted such that when the buffer is full, the oldest items are overwritten first
Queries buf
for the presence of val
Create a new circular buffer of a given size
See the oldest value in the buffer. Works in constant time
Return the oldest value in the buffer, and a new buffer with that value removed
Calculate the allocated size for the buffer.
This is maximum addressable size of the buffer, not how many values it currently contains. For the number of values in the current buffer, see count/1
Convert a circular buffer to a list. The list is ordered by age, oldest to newest. This operation takes linear time
Link to this section Types
Link to this section Functions
Returns the count of the non-empty values in the buffer.
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hi") |> Cbuf.ETS.count()
1
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.count()
0
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.insert(nil) |> Cbuf.ETS.count()
1
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hi") |> Cbuf.ETS.delete() |> Cbuf.ETS.count()
0
iex> buf = Enum.reduce(1..13, Cbuf.ETS.new(5), &Cbuf.ETS.insert(&2, &1))
iex> Cbuf.ETS.delete(buf) |> Cbuf.ETS.count()
4
iex> Cbuf.ETS.new(3) |> Cbuf.ETS.delete() |> Cbuf.ETS.delete() |> Cbuf.ETS.count()
0
Return a new buffer with the oldest item in the buffer removed.
iex> buf = Enum.reduce(1..20, Cbuf.ETS.new(3), fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
iex> buf = Cbuf.ETS.delete(buf)
iex> Cbuf.ETS.peek(buf)
19
iex> buf = Enum.reduce(1..6, Cbuf.ETS.new(5), fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
iex> buf = Cbuf.ETS.delete(buf)
iex> Cbuf.ETS.peek(buf)
3
iex> buf = Enum.reduce(1..6, Cbuf.ETS.new(5), fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
iex> Cbuf.ETS.delete(buf) |> Cbuf.ETS.count()
4
iex> buf = Cbuf.ETS.new(5)
iex> buf = Cbuf.ETS.insert(buf, "ok")
iex> Cbuf.ETS.delete(buf)
#Cbuf<[]>
iex> buf = Cbuf.ETS.new(5)
iex> Cbuf.ETS.delete(buf)
#Cbuf<[]>
Destroy the backing ETS table of a buffer. This function exists if you wish to manually dispose of the ETS table that backs the buffer. The other option is to destroy the process in which the buffer was created, as the ETS table will be disposed of when its parent process dies. See http://erlang.org/doc/man/ets.html for more information about the behavior of ETS tables.
iex> buf = Cbuf.ETS.new(5)
iex> buf = Cbuf.ETS.insert(buf, "ok")
iex> Cbuf.ETS.destroy(buf)
true
iex> buf = Cbuf.ETS.new(5)
iex> buf = Cbuf.ETS.insert(buf, "ok")
iex> Cbuf.ETS.destroy(buf)
iex> Cbuf.ETS.peek(buf)
** (ArgumentError) argument error
Whether or not the buffer is empty.
This value corresponds to when the buffer has a count
of zero, not its size
.
iex> buf = Cbuf.ETS.new(5)
iex> Cbuf.ETS.empty?(buf)
true
iex> buf = Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hi")
iex> Cbuf.ETS.empty?(buf)
false
iex> buf = Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hi") |> Cbuf.ETS.delete()
iex> Cbuf.ETS.empty?(buf)
true
Insert a value into a circular buffer. Values are inserted such that when the buffer is full, the oldest items are overwritten first.
iex> buf = Cbuf.ETS.new(5)
iex> buf |> Cbuf.ETS.insert("a") |> Cbuf.ETS.insert("b")
#Cbuf<["a", "b"]>
iex> buf = Cbuf.ETS.new(3)
iex> Enum.reduce(1..20, buf, fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
#Cbuf<[18, 19, 20]>
iex> buf = Cbuf.ETS.new(1)
iex> Enum.reduce(1..20, buf, fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
#Cbuf<[20]>
Queries buf
for the presence of val
.
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hello") |> Cbuf.ETS.member?("hello")
true
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.insert("hello") |> Cbuf.ETS.member?("nope")
false
Create a new circular buffer of a given size.
iex> Cbuf.ETS.new(5)
#Cbuf<[]>
See the oldest value in the buffer. Works in constant time.
iex> buf = Enum.reduce(1..20, Cbuf.ETS.new(3), fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
iex> Cbuf.ETS.peek(buf)
18
iex> buf = Cbuf.ETS.new(20) |> Cbuf.ETS.insert("ok") |> Cbuf.ETS.insert("fine")
iex> Cbuf.ETS.peek(buf)
"ok"
iex> Cbuf.ETS.new(3) |> Cbuf.ETS.peek()
nil
Return the oldest value in the buffer, and a new buffer with that value removed.
iex> buf = Enum.reduce(1..20, Cbuf.ETS.new(3), fn(val, acc) -> Cbuf.ETS.insert(acc, val) end)
iex> {val, buf} = Cbuf.ETS.pop(buf)
iex> {val, Cbuf.ETS.to_list(buf)} # Elixir has trouble inspecting a nested struct, see https://hexdocs.pm/ex_unit/ExUnit.DocTest.html#module-opaque-types
{18, [19, 20]}
iex> {val, buf} = Cbuf.ETS.new(1) |> Cbuf.ETS.insert("hi") |> Cbuf.ETS.pop()
iex> {val, Cbuf.ETS.to_list(buf)}
{"hi", []}
Calculate the allocated size for the buffer.
This is maximum addressable size of the buffer, not how many values it currently contains. For the number of values in the current buffer, see count/1
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.size()
5
Convert a circular buffer to a list. The list is ordered by age, oldest to newest. This operation takes linear time.
iex> buf = Cbuf.ETS.new(5)
iex> buf |> Cbuf.ETS.insert("a") |> Cbuf.ETS.insert("b") |> Cbuf.ETS.to_list()
["a", "b"]
iex> buf = Cbuf.ETS.new(3)
iex> Enum.reduce(1..20, buf, fn(val, acc) -> Cbuf.ETS.insert(acc, val) end) |> Cbuf.ETS.to_list()
[18, 19, 20]
iex> Cbuf.ETS.new(5) |> Cbuf.ETS.to_list()
[]