An Unsafe pool is like an ordinary pool, except that the create function does
not require an initial element. The pool stores Obj.magic () as the dummy value
for each slot. Such a pool is only safe if one never accesses a slot from a freed
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 freed 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 Obj_array
backing the pool: free, create, grow.
A pool. 'slots will look like ('a1, ..., 'an) Slots.tn, and the pool holds
tuples of type 'a1 * ... * 'an.
pointer_is_valid t pointer returns true iff pointer points to a live tuple in
t, i.e. pointer is not null, not free, and is in the range of t.
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.
id_of_pointer t pointer returns an id that is unique for the lifetime of
pointer's tuple. When the tuple is freed, the id is no longer valid, and
pointer_of_id_exn will fail on it. Pointer.null () has a distinct id from all
non-null pointers.
pointer_of_id_exn t id returns the pointer corresponding to id. It fails if the
tuple corresponding to id was already freed.
create slots ~capacity ~dummy creates an empty pool that can hold up to capacity
N-tuples. The slots of dummy are stored in free tuples. create raises if
capacity < 0 || capacity > max_capacity ~slots_per_tuple.
max_capacity returns the maximum capacity allowed when creating a pool.
capacity returns the maximum number of tuples that the pool can hold.
length returns the number of tuples currently in the pool.
0 <= length t <= capacity t
grow t ~capacity returns a new pool t' with the supplied capacity. The new pool
is to be used as a replacement for t. All live tuples in t are now live in
t', and valid pointers to tuples in t are now valid pointers to the identical
tuple in t'. It is an error to use t after calling grow t.
grow raises if the supplied capacity isn't larger than capacity t.
is_full t returns true if no more tuples can be allocated in t.
get t pointer slot gets slot of the tuple pointed to by pointer in
pool t.
set t pointer slot a sets to a the slot of the tuple pointed to by pointer
in pool t.
In get and set, it is an error to refer to a pointer that has been freed. It
is also an error to use a pointer with any pool other than the one the pointer was
new'd from or grown to. These errors will lead to undefined behavior, but will
not segfault.
unsafe_get is comparable in speed to get for immediate values, and 5%-10% faster
for pointers.
unsafe_get and unsafe_set skip bounds checking, and can thus segfault.