Thursday, February 26, 2009

The mm_manage call

I have been away working on my thesis and on Lush 2 for the last few months. The garbage collector got quite a bit faster since and I made changes to the API. The most recent change was the introduction of the mm_manage call.
mm_manage(const void *p);
With mm_manage you hand to MM a pointer to memory that you allocated with a C library function (malloc, calloc, stdrup, etc.). MM then will take care of it and free the memory for you when it is no longer referenced.

This call makes MM more useful in situations where you get objects from calls into third-party code that uses the C library functions for memory allocation. Of course, you may use mm_manage only for memory objects that are leafs in the dependency graph that MM oversees, and mm_manage assigns those the memory type mt_blob. (The type mt_blob is a predefined, unsized memory type for things that don't contain further memory references).

What if a library does return something more complicated than a blob? For instance, the OpenCV API contains functions like cvFindContours that builds up a complicated data structure, which you need to hold on to and traverse and query with other OpenCV functions. While the address to the data structure created by cvFindContours is, to an OpenCV user, an address to something opaque and pretty much a blob conceptually, you may not simply call free with this address (and therefore you cannot give it to mm_manage).

However, for every call that builds an object, OpenCV has a counterpart, a destructor function, which releases the object. With a little bit more work the mechanism behind mm_manage may be extended to deal with such objects as well. What is needed is a variant mm_manage_foreign, which not only takes a pointer, but, in addition, a custom free function that MM will call instead of free when the object becomes unreachable:
typedef void free_func_t(void *p);
mm_manage_foreign(const void *p, free_func_t *f);
MM would tag those foreign addresses with a special memory type mt_foreign instead of mt_blob and maintain a mapping from foreign pointers to their respective free functions. And mm_manage will then be equivalent to
mm_manage_foreign(p, free);