中断OCaml中的通话

男性主义者

如果要花费太长时间来计算,我想打个电话

try
   do_something ()
with Too_long -> something_else ()

是否可以在OCaml中执行类似的操作?该功能do_something可能无法修改。

静脉血

通常,中断功能的唯一方法是使用信号,如Basile建议的那样。不幸的是,控制流将转移到信号处理程序,因此您将无法返回所需的值。要获得更细粒度的控件,可以do_something在单独的线程中运行第一近似是以下函数:

exception Timeout

let with_timeout timeout f =
  let result = ref None in
  let finished = Condition.create () in
  let guard = Mutex.create () in
  let set x =
    Mutex.lock guard;
    result := Some x;
    Mutex.unlock guard in
  Mutex.lock guard;
  let work () =
    let x = f () in
    set x;
    Condition.signal finished in
  let delay () =
    Thread.delay timeout;
    Condition.signal finished in
  let task = Thread.create work () in
  let wait = Thread.create delay () in
  Condition.wait finished guard;
  match !result with
  | None ->
    Thread.kill task;
    raise Timeout
  | Some x ->
    Thread.kill wait;
    x

具有线程以及具有信号功能的解决方案具有一些缺点。例如,线程在OCaml中的特定迭代点进行切换,通常这是任何分配。因此,如果您的代码不执行任何分配或外部调用,则它可能永远不会屈服于其他线程,并且将永远运行。此类功能的一个很好的例子是let rec f () = f ()在这种情况下,您应该在另一个进程而不是线程中运行函数。OCaml中有许多用于多处理的库,仅举几例:

  1. 映射
  2. 叉车
  3. 异步并行
  4. 平行

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章