Module Core_kernel.Pool

See documentation in Pool_intf.

module type S = Pool_intf.S

This uses an Obj_array.t to implement the pool. We expose that Pointer.t is an int so that OCaml can avoid the write barrier, due to knowing that Pointer.t isn't an OCaml pointer.

module Pointer : sig ... end
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 ‑> Sexplib.Sexp.t) ‑> 'slots t ‑> Sexplib.Sexp.t
val pointer_is_valid : 'slots t ‑> 'slots Pointer.t ‑> Core_kernel__.Import.bool

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.

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 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.

val pointer_of_id_exn : 'slots t ‑> Pointer.Id.t ‑> 'slots Pointer.t

pointer_of_id_exn t id returns the pointer corresponding to id. It fails if the tuple corresponding to id was already freed.

val create : ('tuple'aSlots.t ‑> capacity:Core_kernel__.Import.int ‑> dummy:'tuple ‑> ('tuple'aSlots.t t

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.

val max_capacity : slots_per_tuple:Core_kernel__.Import.int ‑> Core_kernel__.Import.int

max_capacity returns the maximum capacity allowed when creating a pool.

val capacity : 'a t ‑> Core_kernel__.Import.int

capacity returns the maximum number of tuples that the pool can hold.

val length : 'a t ‑> Core_kernel__.Import.int

length returns the number of tuples currently in the pool.

        0 <= length t <= capacity t
val grow : ?⁠capacity:Core_kernel__.Import.int ‑> 'a t ‑> 'a 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.

val is_full : 'a t ‑> Core_kernel__.Import.bool

is_full t returns true if no more tuples can be allocated in t.

val free : 'slots t ‑> 'slots Pointer.t ‑> Core_kernel__.Import.unit

free t pointer frees the tuple pointed to by pointer from t.

val unsafe_free : 'slots t ‑> 'slots Pointer.t ‑> Core_kernel__.Import.unit

unsafe_free t pointer frees the tuple pointed to by pointer without checking pointer_is_valid

val new1 : 'a0 Slots.t1 t ‑> 'a0 ‑> 'a0 Slots.t1 Pointer.t

new<N> t a0 ... a<N-1> returns a new tuple from the pool, with the tuple's slots initialized to a0 ... a<N-1>. new raises if is_full t.

val new2 : ('a0'a1Slots.t2 t ‑> 'a0 ‑> 'a1 ‑> ('a0'a1Slots.t2 Pointer.t
val new3 : ('a0'a1'a2Slots.t3 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> ('a0'a1'a2Slots.t3 Pointer.t
val new4 : ('a0'a1'a2'a3Slots.t4 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> ('a0'a1'a2'a3Slots.t4 Pointer.t
val new5 : ('a0'a1'a2'a3'a4Slots.t5 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> ('a0'a1'a2'a3'a4Slots.t5 Pointer.t
val new6 : ('a0'a1'a2'a3'a4'a5Slots.t6 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> ('a0'a1'a2'a3'a4'a5Slots.t6 Pointer.t
val new7 : ('a0'a1'a2'a3'a4'a5'a6Slots.t7 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> ('a0'a1'a2'a3'a4'a5'a6Slots.t7 Pointer.t
val new8 : ('a0'a1'a2'a3'a4'a5'a6'a7Slots.t8 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7Slots.t8 Pointer.t
val new9 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8Slots.t9 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8Slots.t9 Pointer.t
val new10 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9Slots.t10 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> 'a9 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9Slots.t10 Pointer.t
val new11 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10Slots.t11 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> 'a9 ‑> 'a10 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10Slots.t11 Pointer.t
val new12 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11Slots.t12 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> 'a9 ‑> 'a10 ‑> 'a11 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11Slots.t12 Pointer.t
val new13 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11'a12Slots.t13 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> 'a9 ‑> 'a10 ‑> 'a11 ‑> 'a12 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11'a12Slots.t13 Pointer.t
val new14 : ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11'a12'a13Slots.t14 t ‑> 'a0 ‑> 'a1 ‑> 'a2 ‑> 'a3 ‑> 'a4 ‑> 'a5 ‑> 'a6 ‑> 'a7 ‑> 'a8 ‑> 'a9 ‑> 'a10 ‑> 'a11 ‑> 'a12 ‑> 'a13 ‑> ('a0'a1'a2'a3'a4'a5'a6'a7'a8'a9'a10'a11'a12'a13Slots.t14 Pointer.t
val get_tuple : ('tuple'aSlots.t t ‑> ('tuple'aSlots.t Pointer.t ‑> 'tuple

get_tuple t pointer allocates an OCaml tuple isomorphic to the pool t's tuple pointed to by pointer. The tuple gets copied, but its slots do not.

val get : ('a'variantSlots.t t ‑> ('a'variantSlots.t Pointer.t ‑> ('variant'slotSlot.t ‑> 'slot

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.

val unsafe_get : ('a'variantSlots.t t ‑> ('a'variantSlots.t Pointer.t ‑> ('variant'slotSlot.t ‑> 'slot
val set : ('a'variantSlots.t t ‑> ('a'variantSlots.t Pointer.t ‑> ('variant'slotSlot.t ‑> 'slot ‑> Core_kernel__.Import.unit
val unsafe_set : ('a'variantSlots.t t ‑> ('a'variantSlots.t Pointer.t ‑> ('variant'slotSlot.t ‑> 'slot ‑> Core_kernel__.Import.unit
module Unsafe : sig ... end

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 freed tuple.

module Debug : functor (Pool : S) -> sig ... end

Debug builds a pool in which every function can run invariant on its pool argument(s) and/or print a debug message to stderr, as determined by !check_invariant and !show_messages, which are initially both true.

module Error_check : functor (Pool : S) -> S

Error_check builds a pool that has additional error checking for pointers, in particular to detect using a freed pointer or multiply freeing a pointer.