【发布时间】:2013-11-14 10:24:00
【问题描述】:
我正在尝试将OBus 库与Lwt_react 一起使用。这对属性和信号使用“函数式反应式编程”。
问题(如React documentation 中所述)是OCaml 可能会在您仍在使用它时垃圾收集您的回调。有一个keep 函数,它可以永久保存处理程序,但我不希望这样。我确实想最终释放它,而不是在我仍然需要它的时候。
所以,我想我会将处理程序附加到开关:
let keep ~switch handler =
Lwt_switch.add_hook (Some switch) (fun () ->
ignore handler;
Lwt.return ()
)
但是我的事件处理程序无论如何都会被垃圾收集(这是有道理的,因为关闭开关的代码在信号到达时被调用,所以它只是首先保持开关处于活动状态的信号处理程序)。
这是我的代码的简化(独立)版本:
(* ocamlfind ocamlopt -package react,lwt,lwt.react,lwt.unix -linkpkg -o test test.ml *)
let finished_event, fire_finished = React.E.create ()
let setup () =
let switch = Lwt_switch.create () in
let finished, waker = Lwt.wait () in
let handler () = Lwt.wakeup waker () in
let dont_gc_me = Lwt_react.E.map handler finished_event in
ignore dont_gc_me; (* What goes here? *)
print_endline "Waiting for signal...";
Lwt.bind finished (fun () -> Lwt_switch.turn_off switch)
let () =
let finished = Lwt.protected (setup ()) in
Gc.full_major (); (* Force GC, to demonstrate problem *)
fire_finished (); (* Simulate send *)
Lwt_main.run finished;
print_endline "Done";
没有Gc.full_major 行,这通常打印Done。有了它,它就挂在Waiting for signal...。
编辑:我已将 setup(真实代码)从测试驱动程序中分离出来,并添加了一个 Lwt.protected 包装器,以避免因 Lwt 取消而掩盖问题。
【问题讨论】:
标签: garbage-collection ocaml reactive-programming ocaml-lwt