Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are custom blocks ever copied by OCaml?

Imagine I've a C library called libcat for interacting with my cat fluffy. I'm therefore writing bindings for OCaml to simplify interactions with fluffy.

module type CAT = sig 
   type cat
   val find : ... -> cat
   val feed : cat -> unit
   ...
end ;;
module Cat : CAT = ...

There is considerable memory management already built into libcat, like say caching, freeing destroyed toys, and maybe even a limited scope garbage collector for emptying the litter. Yet, overall libcat requires that users explicitly free unused resources, like lost toys.

I've written a C stub for Cat.find that finds and allocates the cat using libcat's cat_find routine, but then stores the resulting pointer to the cat in a custom block created with caml_alloc_custom.

I've added a finalize method into the custom_operations struct passed into caml_alloc_custom. Crucially, I've made this finalize method free the cat because I'm sick of her scratching on the door while I'm answering a phone exception.

I'm now worried that, if OCaml ever duplicates a custom block of type Cat.cat, then OCaml's garbage collector may free fluffy while we're still playing. For example :

let fluffy = Cat.find ;;
fluffy.yodel ;;
let meow = fluffy ;;
...
meow.feed ;;

We must assume that ... will trigger OCaML's garbage collector after the last explicit reference to fluffy, say by breaking dishes. Is this garbage collection event going to call fluffy's finalize method and free her? Or will meow simply refer to fluffy's original custom block, thus preventing fluffy from being freed?

I'd imagine fluffy isn't freed in this situation, well otherwise OCaml would surely ask for a duplicate method in custom_operations struct, but I felt it better to ask. If fluffy might in fact be freed, can I prevent this by only letting OCaml handle her by reference? Roughly :

  type cat_name = real_cat ref
  type real_cat
like image 426
Jeff Burdges Avatar asked Nov 06 '22 01:11

Jeff Burdges


1 Answers

The custom block itself, that is, the bytes obtained from caml_alloc_custom, is part of the Caml heap and can be moved like any other object.¹ It's very common for the custom block to contain pointers to data structures that are also accessed by C² code and live outside the Caml heap; Caml treats the contents of the custom block as opaque and doesn't even know whether it contains pointers, so it won't touch these data structures.

When you write let meow = fluffy, there is no copy going on: you're just giving a new name to the same object. Caml will never duplicate a custom block; if you want that, you have to provide a copy_cat primitive in your library.

¹ Only the minor garbage collector and the compactor actually move blocks around, the major gc doesn't. But that's not something you should rely on.

² Or Fortran, or whatever other language your program or library uses.

like image 99
Gilles 'SO- stop being evil' Avatar answered Nov 11 '22 13:11

Gilles 'SO- stop being evil'