Browse thread
On the C interface, callbacks, and global roots
- Thomas Fischbacher
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Thomas Fischbacher <Thomas.Fischbacher@P...> |
| Subject: | On the C interface, callbacks, and global roots |
Suppose I have an opaque C object obj, for which there is a function that allows me to register a C callback function f_cb (and a void* closure data pointer, let's call it f_cb_data). In principle, it is possible to lift the callback-registering up to the ML level, so that we can register a ML function as a callback for the ML-wrapped object. I suppose that the proper way to do this is to internally represent obj as a ML custom block with a special finalizer which will hold (1) a C pointer to obj, and (2) a C pointer to malloc()'d space holding a global GC root pointing to the ML callback function. The static-in-memory address of malloc'd space will then hold the ML callback function. So far, so good. But - how should one proceed if f_cb's signature is such that it will receive obj as its first argument? Evidently, if we store the ML variant of f_cb (which will be contained somewhere in f_cb_data, and f_cb will be a wrapper executing the ML callback stored in f_cb_data) in a global root, this will make obj non-collectable. The problem is that we should not place something under a global root which contains a reference back to the object responsible for un-registering the global root in its finalizer. As far as I can see, the cleanest solution to this dilemma would be to introduce yet another type of ML block with a special meaning to the garbage collector: one that holds a pointer to nonmoving non-heap memory that can hold ML values, plus additional information on the number of such ML values, and a pointer to a de-allocation function (with its own closure arg, I'd say). Seen in a different way, the problem of creating non-reclaimable values even exists if the ML callback function happens to be a closure containing the ML-wrapped obj. Somehow, the whole idea of using global roots like this feels a bit wrong to me. Did I miss something essential? How should one rather proceed instead? -- regards, tf@cip.physik.uni-muenchen.de (o_ Thomas Fischbacher - http://www.cip.physik.uni-muenchen.de/~tf //\ (lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y) V_/_ (if (= x 0) y (g g (- x 1) (* x y)))) n 1)) (Debian GNU)