module Error_check:
Error_check
builds a pool that has additional error checking for pointers, in
particular to detect using a free
d pointer or multiply free
ing a pointer.
Error_check
has a significant performance cost, but less than that of Debug
.
One can compose Debug
and Error_check
, e.g:
module M = Debug (Error_check (Obj_array))
Parameters: |
|
module Slots:Tuple_type.Slots
module Slot:Tuple_type.Slot
module Pointer:sig
..end
type 'slots
t
'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.
pointer_of_id_exn_is_supported
says whether the implementation supports
pointer_of_id_exn
; if not, it will always raise. We can not use the usual idiom
of making pointer_of_id_exn
be an Or_error.t
due to problems with the value
restriction.
val pointer_of_id_exn_is_supported : bool
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.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 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 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.
pointer_of_id_exn_is_supported
says whether the implementation supports
pointer_of_id_exn
; if not, it will always raise. We can not use the usual idiom
of making pointer_of_id_exn
be an Or_error.t
due to problems with the value
restriction.
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.
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
.
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.