Пользовательские блоки когда-либо копируются OCaml? - PullRequest
5 голосов
/ 19 марта 2011

Представьте, что у меня есть библиотека 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

1 Ответ

2 голосов
/ 20 марта 2011

Сам пользовательский блок, то есть байты, полученные из caml_alloc_custom, является частью кучи Caml и может быть перемещен как любой другой объект. Обычно пользовательский блок содержит указатели на структуры данных, которыетакже доступны по коду C² и живут вне кучи Caml;Caml рассматривает содержимое пользовательского блока как непрозрачное и даже не знает, содержит ли он указатели, поэтому не будет касаться этих структур данных.

Когда вы пишете let meow = fluffy, копирование не происходит: вы просто даете новое имя тому же объекту.Caml никогда не будет дублировать пользовательский блок;если вы хотите этого, вы должны предоставить copy_cat примитив в вашей библиотеке.

¹ Только незначительный сборщик мусора и компактор фактически перемещают блоки, а главный gc - нет.Но на это не стоит полагаться.

² Или Fortran, или любой другой язык, используемый вашей программой или библиотекой.

...