(** Mark objects as 'ancient' so they are taken out of the OCaml heap.
- * $Id: ancient.mli,v 1.2 2006-09-27 15:36:18 rich Exp $
+ * $Id: ancient.mli,v 1.6 2006-10-09 12:18:05 rich Exp $
*)
type 'a ancient
* Forgetting to delete an ancient object results in a memory leak.
*)
+val is_ancient : 'a -> bool
+ (** [is_ancient ptr] returns true if [ptr] is an object on the ancient
+ * heap.
+ *)
+
(** {6 Shared memory mappings} *)
-val share : Unix.file_descr -> 'a -> 'a ancient
- (** [share fd obj] does the same as {!Ancient.mark} except
+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.
+ *)
+
+val share : 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 file [fd].
- * [fd] should be a writable, zero-length file (see
- * {!Unix.openfile}).
+ * 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. They are
+ * indexed using integers in the range [0..max_key] (the limit
+ * is hard-coded in [mmalloc/mmprivate.h]). 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 attach : Unix.file_descr -> 'a ancient
- (** [attach fd] takes an existing file which was created by
- * {!Ancient.share} and accesses the object contained
- * in it.
+val get : md -> int -> 'a ancient
+ (** [get md key] returns the object indexed by [key] in the
+ * attached file.
*
- * You need to force the return type to be the correct type
- * for the object contained in the file. As with Marshal,
- * the type is not checked, and if it is wrong a segfault
- * is likely.
+ * The key is in the range [0..max_key] (the limit is hard-coded in
+ * [mmalloc/mmprivate.h]). If you do not wish to use this feature,
+ * just pass [0] as the key when sharing / getting.
*
- * Do not call {!Ancient.delete} on a mapping created like this.
- * Instead, call {!Ancient.detach} and, if necessary, delete the
- * underlying file.
- *)
-
-val detach : 'a ancient -> unit
- (** [detach obj] detaches from a shared mapping.
+ * 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].
*
- * @raise [Invalid_argument "detached"] if the object has been detached.
+ * @raises [Not_found] if no object is associated with the key.
*)
+
+val max_key : int