+
+CAMLprim value
+ancient_share (value fdv, value obj)
+{
+ CAMLparam2 (fdv, obj);
+ CAMLlocal1 (proxy);
+
+ int fd = Int_val (fd);
+ void *md = mmalloc_attach (fd, 0);
+ if (md == 0) {
+ perror ("mmalloc_attach");
+ caml_failwith ("mmalloc_attach");
+ }
+
+ proxy = do_mark (obj, mrealloc, mfree, md);
+
+ // Save the address of the object within the mmalloc area. We need
+ // it when attaching.
+ mmalloc_setkey (md, 0, (void *) Field (proxy, 0));
+
+ CAMLreturn (proxy);
+}
+
+CAMLprim value
+ancient_attach (value fdv)
+{
+ CAMLparam1 (fdv);
+ CAMLlocal1 (proxy);
+
+ int fd = Int_val (fd);
+ void *md = mmalloc_attach (fd, 0);
+ if (md == 0) {
+ perror ("mmalloc_attach");
+ caml_failwith ("mmalloc_attach");
+ }
+
+ proxy = caml_alloc (2, Abstract_tag);
+ Field (proxy, 0) = (value) mmalloc_getkey (md, 0);
+ Field (proxy, 1) = (value) md;
+
+ CAMLreturn (proxy);
+}
+
+CAMLprim value
+ancient_detach (value obj)
+{
+ CAMLparam1 (obj);
+ CAMLlocal1 (v);
+
+ int size = Wosize_val (obj);
+ if (size < 2) caml_failwith ("Ancient.detach: not an attached object");
+
+ v = Field (obj, 0);
+ if (Is_long (v)) caml_invalid_argument ("detached");
+
+ void *md = (void *) Field (obj, 1);
+ if (mmalloc_detach (md) != 0) {
+ perror ("mmalloc_detach");
+ caml_failwith ("mmalloc_detach");
+ }
+
+ // Replace the proxy (a pointer) with an int 0 so we know it's
+ // been detached in future.
+ Field (obj, 0) = Val_long (0);
+
+ CAMLreturn (Val_unit);
+}