module Ancient:sig
..end
Mark objects as 'ancient' so they are taken out of the OCaml heap.
type 'a
ancient
val mark : 'a -> 'a ancient
mark obj
copies obj
and all objects referenced
by obj
out of the OCaml heap. It returns the proxy
for obj
.
The copy of obj
accessed through the proxy MUST NOT be mutated.
If obj
represents a large object, then it is a good
idea to call Gc.compact
after marking to recover the
OCaml heap memory.
val follow : 'a ancient -> 'a
val delete : 'a ancient -> unit
val is_ancient : 'a -> bool
is_ancient ptr
returns true if ptr
is an object on the ancient
heap.
val address_of : 'a -> nativeint
address_of obj
returns the address of obj
, or 0n
if obj
is not a block.
type
md
Memory descriptor handle.
val attach : Unix.file_descr -> nativeint -> md
attach fd baseaddr
attaches to a new or existing file
which may contain shared objects.
Initially fd
should be a read/writable, zero-length file
(for example you could create this using Unix.openfile
and
passing the flags O_RDWR
, O_TRUNC
, O_CREAT
).
One or more objects can then be shared in this file
using Unix.share
.
For new files, baseaddr
specifies the virtual address to
map the file. Specifying Nativeint.zero
(0n
) here lets mmap(2)
choose this, but on some platforms (notably Linux/AMD64)
mmap
chooses very unwisely, tending to map the memory
just before libc
with hardly any headroom to grow. If
you encounter this sort of problem (usually a segfault or
illegal instruction inside libc), then look at /proc/PID/maps
and choose a more suitable address.
If the file was created previously, then the baseaddr
is
ignored. The underlying mmalloc
library will map the
file in at the same place as before.
val detach : md -> unit
detach md
detaches from an existing file, and closes it.
md -> int -> 'a -> 'a ancient
: share md key obj
does the same as Ancient.mark
except
that instead of copying the object into local memory, it
writes it into memory which is backed by the attached file.
Shared mappings created this way may be shared between
other OCaml processes which can access the underlying
file. See Ancient.attach
, Ancient.detach
.
More than one object can be stored in a file. The key
parameter controls which object is written/overwritten by share
.
If you do not wish to use this feature, just pass 0
as the key.
Do not call Ancient.delete
on a mapping created like this.
Instead, call Ancient.detach
and, if necessary, delete the
underlying file.
Caution when sharing files/objects between processes:
The underlying mmalloc
library does not do any sort of
locking, so all calls to share
must ensure that they have
exclusive access to the underlying file while in progress.
(Other processes should not even call Ancient.get
while
this is happening, but it seems safe to be just reading an
ancient object from the file).
val get : md -> int -> 'a ancient
get md key
returns the object indexed by key
in the
attached file.
For details of the key
parameter see Ancient.share
.
You need to annotate the returned object with the correct
type. As with the Marshal module, there is no type checking,
and setting the wrong type will likely cause a segfault
or undefined behaviour. Note that the returned object has
type sometype ancient
, not just sometype
.
type
info = {
|
i_size : |
(* | Allocated size, bytes. | *) |
}
Extra information fields. See Ancient.mark_info
and
Ancient.share_info
.
val mark_info : 'a -> 'a ancient * info
Same as Ancient.mark
, but also returns some extra information.
md -> int -> 'a -> 'a ancient * info
: Same as Ancient.share
, but also returns some extra information.