From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 2AC427F7B4 for ; Sat, 1 Feb 2014 17:42:05 +0100 (CET) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of goswin-v-b@web.de) identity=pra; client-ip=212.227.15.4; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="goswin-v-b@web.de"; x-sender="goswin-v-b@web.de"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of goswin-v-b@web.de) identity=mailfrom; client-ip=212.227.15.4; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="goswin-v-b@web.de"; x-sender="goswin-v-b@web.de"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mout.web.de) identity=helo; client-ip=212.227.15.4; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="goswin-v-b@web.de"; x-sender="postmaster@mout.web.de"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjwCAC8j7VLU4w8Em2dsb2JhbABZvCqGWhYOAQEBAQEGCwsJFCiCZns0BSghiAMBGJxSpigfigKTSASYKYYyEoQMiUGBPw X-IPAS-Result: AjwCAC8j7VLU4w8Em2dsb2JhbABZvCqGWhYOAQEBAQEGCwsJFCiCZns0BSghiAMBGJxSpigfigKTSASYKYYyEoQMiUGBPw X-IronPort-AV: E=Sophos;i="4.95,760,1384297200"; d="scan'208";a="56433626" Received: from mout.web.de ([212.227.15.4]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 01 Feb 2014 17:42:04 +0100 Received: from frosties.localnet ([37.49.32.119]) by smtp.web.de (mrweb001) with ESMTPSA (Nemesis) id 0MCZP8-1W1Lv40t9O-009Prx for ; Sat, 01 Feb 2014 17:42:04 +0100 Received: from mrvn by frosties.localnet with local (Exim 4.80) (envelope-from ) id 1W9ddr-0000q3-GO for caml-list@inria.fr; Sat, 01 Feb 2014 17:42:03 +0100 Date: Sat, 1 Feb 2014 17:42:03 +0100 From: Goswin von Brederlow To: Ocaml Mailing List Message-ID: <20140201164203.GG1783@frosties> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Provags-ID: V03:K0:p+FaSwAO1kh7ftZsZHMbp42pBaaus8cIRDHL8Rej9uBzZjXzSf5 Vttho2MmmOe425pcQtqcTczJDUk0wItlZOQi6GUCo3anKND/I46ZHYcon4lip1xzyBeHQJd zDq6donudb1NH3ox10aFL/Wo2KvmyRUIZehFmZ44qi90o2RqyIjbmKpwSEfNxqY6cvjpX2M Q4WGZMfVw2EEtku4CFF+A== Subject: [Caml-list] Why is struct caml_ba_proxy allocated outside the GC heap and why doesn't it have a finalizer? Hi, in ZMQ (C library) I have zmq_msg_t structs that contain some metadata (like the length) and potentially a pointer to data. For short messages the data is part of zmq_msg_t and for larger it is allocated seperately. The zmq_msg_t is an abstract type and I need to call zmq_msg_close() when I no longer need that data of a message. Now when I write bindings for this I would like to use Bigarray to grant access to the data and there I run into a problem. I need to call zmq_msg_close() when the Bigarray is freed by the GC. Normaly I could use Gc.finalise to register a function that calls zmq_msg_close(). But not so with Bigarray because they can be sliced. The slicing creates a new Bigarray that points to the same data. The data can only be freed when every Bigarray pointing to it is unreachable. The way this works now in ocaml is using a struct caml_ba_proxy. The problem for me now is that the caml_ba_proxy is allocated outside the GC heap and not reachable from the ocaml side. But I would have to call Gc.finalise for the caml_ba_proxy object instead of the Bigarray. Currently a Bigarray is a custom block that optionally contains a pointer to the caml_ba_proxy. The pointer is set when a Bigarray is sliced for the first time. And the caml_ba_proxy does reference counting. A Bigarray also has a flag to say that the memory it points to is not to be freed by the GC, is to be freed or is to be munmap()ed, hardcoding 3 options. I can see 3 possible improvements there: 1) add a "void (*free)(struct caml_ba_proxy *)" to the caml_ba_proxy structure that, if not NULL, gets called when the caml_ba_proxy is freed. In the case of GC managed memory this would be set to free the memory. In the case of mmap it would be set to munmap. And in unmanaged memory it would be NULL. And for C bindings using Bigarray they can pass in their own free function pointer. 2) Like 1 but also add a "void *private". Additional state for the Bigarray can be stored there. In my case a pointer to the zmq_msg_t would be stored. Actually forget about 1 and just do 2. 3) Bigarray becomes a normal OCaml record and the caml_ba_proxy becomes a custom block. The finaliser, compare, serialise, ... functions of the Bigarray and some flags move to the caml_ba_proxy, which is no longer optional. Reference counting gets dropped since the GC already covers that better now and the Bigarray module adds a function to add finalisers to the caml_ba_proxy object. So what do you think? Would it make sense to patch ocaml to support option 2 or 3? MfG Goswin