Представьте, что у меня есть библиотека C libcat для взаимодействия с моей пушистой кошкой. Поэтому я пишу привязки для OCaml, чтобы упростить взаимодействие с пушистым.
module type CAT = sig
type cat
val find : ... -> cat
val feed : cat -> unit
...
end ;;
module Cat : CAT = ...
В libcat уже встроено значительное управление памятью, например, кеширование, освобождение уничтоженных игрушек и, возможно, сборщик мусора с ограниченным объемом для удаления мусора. Тем не менее, в целом libcat требует, чтобы пользователи явно освобождали неиспользуемые ресурсы, такие как потерянные игрушки.
Я написал заглушку C для Cat.find, которая находит и размещает кошку с помощью подпрограммы libcat cat_find, но затем сохраняет полученный указатель на кошку в пользовательском блоке, созданном с помощью caml_alloc_custom.
Я добавил метод finalize в структуру custom_operations, переданную в caml_alloc_custom. Важно отметить, что я сделал этот метод завершения свободным, потому что мне надоело, что она царапает дверь, когда отвечаю на телефонное исключение.
Теперь я беспокоюсь, что если OCaml когда-либо дублирует пользовательский блок типа Cat.cat, то сборщик мусора в OCaml может освободиться, пока мы еще играем. Например:
let fluffy = Cat.find ;;
fluffy.yodel ;;
let meow = fluffy ;;
...
meow.feed ;;
Мы должны предположить, что ... вызовет сборщик мусора в OCaML после последней явной ссылки на пушистый, скажем, разбивая тарелки. Это событие сбора мусора вызовет метод завершения пушистика и освободит ее? Или мяу будет просто ссылаться на оригинальный пользовательский блок пушистика, предотвращая освобождение пушистика?
Я бы предположил, что пушистый не освобождается в этой ситуации, в противном случае OCaml наверняка запросит дублирующий метод в структуре custom_operations, но я чувствую, что лучше спросить. Если пушистика может быть на самом деле освобождена, могу ли я предотвратить это, разрешая OCaml обращаться с ней по ссылке? Примерно:
type cat_name = real_cat ref
type real_cat