我想使用OBus库和Lwt_react一起编程。这个库使用函数响应编程处理属性和信号。
问题在于OCaml可能会在你仍在使用回调函数时进行垃圾收集,这一点在React文档中也有提到。有一个
所以,我想把处理程序附加到一个开关上。
没有
编辑:我已经将真正的代码从测试驱动程序中拆分出来,并添加了一个
问题在于OCaml可能会在你仍在使用回调函数时进行垃圾收集,这一点在React文档中也有提到。有一个
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...
上。编辑:我已经将真正的代码从测试驱动程序中拆分出来,并添加了一个
Lwt.protected
封装,以避免 Lwt 取消操作的意外掩盖问题。
Gc
行之前添加let finished = Lwt.protected finished in
会再次破坏它。 - Thomas Leonard