Module Tuple_pool.Unsafe
An Unsafe
pool is like an ordinary pool, except that the create
function does not require an initial element. The pool stores a dummy value for each slot. Such a pool is only safe if one never accesses a slot from a free
d tuple.
It makes sense to use Unsafe
if one has a small constrained chunk of code where one can prove that one never accesses a free
d tuple, and one needs a pool where it is difficult to construct a dummy value.
Some Unsafe
functions are faster than the corresponding safe version because they do not have to maintain values with the correct represention in the Uniform_array
backing the pool: free
, create
, grow
.
include S with type 'a Pointer.t = private int
module Slots : Tuple_type.Slots
module Slot : Tuple_type.Slot
type 'slots t
A pool.
'slots
will look like('a1, ..., 'an) Slots.tn
, and the pool holds tuples of type'a1 * ... * 'an
.
val sexp_of_t : ('slots -> Ppx_sexp_conv_lib.Sexp.t) -> 'slots t -> Ppx_sexp_conv_lib.Sexp.t
include Core_kernel.Invariant.S1 with type 'a t := 'a t
val invariant : 'a Base__.Invariant_intf.inv -> 'a t Base__.Invariant_intf.inv
val pointer_is_valid : 'slots t -> 'slots Pointer.t -> bool
pointer_is_valid t pointer
returnstrue
iffpointer
points to a live tuple int
, i.e.pointer
is not null, not free, and is in the range oft
.A pointer might not be in the range of a pool if it comes from another pool for example. In this case unsafe_get/set functions would cause a segfault.
val id_of_pointer : 'slots t -> 'slots Pointer.t -> Pointer.Id.t
id_of_pointer t pointer
returns an id that is unique for the lifetime ofpointer
's tuple. When the tuple is freed, the id is no longer valid, andpointer_of_id_exn
will fail on it.Pointer.null ()
has a distinct id from all non-null pointers.
val pointer_of_id_exn : 'slots t -> Pointer.Id.t -> 'slots Pointer.t
pointer_of_id_exn t id
returns the pointer corresponding toid
. It fails if the tuple corresponding toid
was alreadyfree
d.
val create : ('tuple, _) Slots.t as 'slots -> capacity:int -> dummy:'tuple -> 'slots t
create slots ~capacity ~dummy
creates an empty pool that can hold up tocapacity
N-tuples. The slots ofdummy
are stored in free tuples.create
raises ifcapacity < 0 || capacity > max_capacity ~slots_per_tuple
.
val max_capacity : slots_per_tuple:int -> int
max_capacity
returns the maximum capacity allowed when creating a pool.
val capacity : _ t -> int
capacity
returns the maximum number of tuples that the pool can hold.
val length : _ t -> int
length
returns the number of tuples currently in the pool.0 <= length t <= capacity t
val grow : ?capacity:int -> 'a t -> 'a t
grow t ~capacity
returns a new poolt'
with the supplied capacity. The new pool is to be used as a replacement fort
. All live tuples int
are now live int'
, and valid pointers to tuples int
are now valid pointers to the identical tuple int'
. It is an error to uset
after callinggrow t
.grow
raises if the supplied capacity isn't larger thancapacity t
.
val is_full : _ t -> bool
is_full t
returnstrue
if no more tuples can be allocated int
.
val free : 'slots t -> 'slots Pointer.t -> unit
free t pointer
frees the tuple pointed to bypointer
fromt
.
val unsafe_free : 'slots t -> 'slots Pointer.t -> unit
unsafe_free t pointer
frees the tuple pointed to bypointer
without checkingpointer_is_valid
val new1 : 'a0 Slots.t1 as 'slots t -> 'a0 -> 'slots Pointer.t
new<N> t a0 ... a<N-1>
returns a new tuple from the pool, with the tuple's slots initialized toa0
...a<N-1>
.new
raises ifis_full t
.
val new2 : ('a0, 'a1) Slots.t2 as 'slots t -> 'a0 -> 'a1 -> 'slots Pointer.t
val new3 : ('a0, 'a1, 'a2) Slots.t3 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'slots Pointer.t
val new4 : ('a0, 'a1, 'a2, 'a3) Slots.t4 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'slots Pointer.t
val new5 : ('a0, 'a1, 'a2, 'a3, 'a4) Slots.t5 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'slots Pointer.t
val new6 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5) Slots.t6 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'slots Pointer.t
val new7 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6) Slots.t7 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'slots Pointer.t
val new8 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7) Slots.t8 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'slots Pointer.t
val new9 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8) Slots.t9 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'slots Pointer.t
val new10 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9) Slots.t10 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'a9 -> 'slots Pointer.t
val new11 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10) Slots.t11 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'a9 -> 'a10 -> 'slots Pointer.t
val new12 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10, 'a11) Slots.t12 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'a9 -> 'a10 -> 'a11 -> 'slots Pointer.t
val new13 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10, 'a11, 'a12) Slots.t13 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'a9 -> 'a10 -> 'a11 -> 'a12 -> 'slots Pointer.t
val new14 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10, 'a11, 'a12, 'a13) Slots.t14 as 'slots t -> 'a0 -> 'a1 -> 'a2 -> 'a3 -> 'a4 -> 'a5 -> 'a6 -> 'a7 -> 'a8 -> 'a9 -> 'a10 -> 'a11 -> 'a12 -> 'a13 -> 'slots Pointer.t
val get_tuple : ('tuple, _) Slots.t as 'slots t -> 'slots Pointer.t -> 'tuple
get_tuple t pointer
allocates an OCaml tuple isomorphic to the poolt
's tuple pointed to bypointer
. The tuple gets copied, but its slots do not.
val get : (_, 'variant) Slots.t as 'slots t -> 'slots Pointer.t -> ('variant, 'slot) Slot.t -> 'slot
get t pointer slot
getsslot
of the tuple pointed to bypointer
in poolt
.set t pointer slot a
sets toa
theslot
of the tuple pointed to bypointer
in poolt
.In
get
andset
, it is an error to refer to a pointer that has beenfree
d. It is also an error to use a pointer with any pool other than the one the pointer wasnew
'd from orgrow
n to. These errors will lead to undefined behavior, but will not segfault.unsafe_get
is comparable in speed toget
for immediate values, and 5%-10% faster for pointers.unsafe_get
andunsafe_set
skip bounds checking, and can thus segfault.
val unsafe_get : (_, 'variant) Slots.t as 'slots t -> 'slots Pointer.t -> ('variant, 'slot) Slot.t -> 'slot
val set : (_, 'variant) Slots.t as 'slots t -> 'slots Pointer.t -> ('variant, 'slot) Slot.t -> 'slot -> unit
val unsafe_set : (_, 'variant) Slots.t as 'slots t -> 'slots Pointer.t -> ('variant, 'slot) Slot.t -> 'slot -> unit