# Module type Pool_intf.Pool.S

    module type S = Pool_intf.S

    module Slots: Tuple_type.Slots

    module Slot: Tuple_type.Slot

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

    include Invariant.S1

    val pointer_is_valid : 'slots t -> 'slots Pointer.t -> 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 `free`d.

    val create : ('tuple, 'a) Slots.t ->
           capacity:int -> dummy:'tuple -> ('tuple, 'a) Slots.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:int -> int

`max_capacity` returns the maximum capacity allowed when creating a pool.

    val capacity : 'a t -> int

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

    val length : 'a 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 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 -> bool

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

    val free : 'slots t -> 'slots Pointer.t -> unit

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

    val unsafe_free : 'slots t -> 'slots Pointer.t -> 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, 'a1) Slots.t2 t ->
           'a0 -> 'a1 -> ('a0, 'a1) Slots.t2 Pointer.t

    val new3 : ('a0, 'a1, 'a2) Slots.t3 t ->
           'a0 -> 'a1 -> 'a2 -> ('a0, 'a1, 'a2) Slots.t3 Pointer.t

    val new4 : ('a0, 'a1, 'a2, 'a3) Slots.t4 t ->
           'a0 ->
           'a1 -> 'a2 -> 'a3 -> ('a0, 'a1, 'a2, 'a3) Slots.t4 Pointer.t

    val new5 : ('a0, 'a1, 'a2, 'a3, 'a4) Slots.t5 t ->
           'a0 ->
           'a1 ->
           'a2 -> 'a3 -> 'a4 -> ('a0, 'a1, 'a2, 'a3, 'a4) Slots.t5 Pointer.t

    val new6 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5) Slots.t6 t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 -> 'a5 -> ('a0, 'a1, 'a2, 'a3, 'a4, 'a5) Slots.t6 Pointer.t

    val new7 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6) Slots.t7 t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 ->
           'a5 ->
           'a6 -> ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6) Slots.t7 Pointer.t

    val new8 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7) Slots.t8 t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 ->
           'a5 ->
           'a6 ->
           'a7 ->
           ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7) Slots.t8 Pointer.t

    val new9 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8) Slots.t9 t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 ->
           'a5 ->
           'a6 ->
           'a7 ->
           'a8 ->
           ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8) Slots.t9 Pointer.t

    val new10 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9) Slots.t10 t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 ->
           'a5 ->
           'a6 ->
           'a7 ->
           'a8 ->
           'a9 ->
           ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9) Slots.t10
           Pointer.t

    val new11 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10) Slots.t11
           t ->
           'a0 ->
           'a1 ->
           'a2 ->
           'a3 ->
           'a4 ->
           'a5 ->
           'a6 ->
           'a7 ->
           'a8 ->
           'a9 ->
           'a10 ->
           ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10) Slots.t11
           Pointer.t

    val new12 : ('a0, 'a1, 'a2, 'a3, 'a4, 'a5, 'a6, 'a7, 'a8, 'a9, 'a10, 'a11) Slots.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, 'a11) Slots.t12
           Pointer.t

    val get_tuple : ('tuple, 'a) Slots.t t ->
           ('tuple, 'a) Slots.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, 'variant) Slots.t t ->
           ('a, 'variant) Slots.t Pointer.t ->
           ('variant, 'slot) Slot.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 `free`d. It is also an error to use a pointer with any pool other than the one the pointer was `new`'d from or `grow`n 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, 'variant) Slots.t t ->
           ('a, 'variant) Slots.t Pointer.t ->
           ('variant, 'slot) Slot.t -> 'slot

    val set : ('a, 'variant) Slots.t t ->
           ('a, 'variant) Slots.t Pointer.t ->
           ('variant, 'slot) Slot.t -> 'slot -> unit

    val unsafe_set : ('a, 'variant) Slots.t t ->
           ('a, 'variant) Slots.t Pointer.t ->
           ('variant, 'slot) Slot.t -> 'slot -> unit

    val sexp_of_t : ('slots -> Sexplib.Sexp.t) -> 'slots t -> Sexplib.Sexp.t

`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 `free`d.
`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`.
default is `2 * capacity t`
`is_full t` returns `true` if no more tuples can be allocated in `t`.
`free t pointer` frees the tuple pointed to by `pointer` from `t`.
`unsafe_free t pointer` frees the tuple pointed to by `pointer` without checking `pointer_is_valid`
`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`.
`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.
`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 `free`d. It is also an error to use a pointer with any pool other than the one the pointer was `new`'d from or `grow`n 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.