Ocaml Lwt.wait()

G41*_*143 1 ocaml ocaml-lwt

我对lwt的wait函数以及如何在自己的自定义函数中使用它(该函数将返回一个Lwt.t线程)有疑问。首先让我们给你看一个例子。

open Lwt_io
open Lwt.Infix

let i, o = Lwt_io.pipe()

let get_int () =
  let t, w = Lwt.wait() in
  (*what do I do here to provide the sleeping thread*)
  (*with a possible integer reply*)
  Lwt_io.read_int(i) >>= fun i -> Lwt.wakeup w i;
  t

let ans = get_int()
Run Code Online (Sandbox Code Playgroud)

在上面的函数中,我调用wait来产生一个睡眠线程及其唤醒器,但是我不确定如何为睡眠线程提供可能的整数答复,并且仍然能够从get_int函数返回睡眠线程。我提供了一行(Lwt_io.read_int(i)>> = fun i-> Lwt.wakeup wi;),该行似乎有效,但是我不确定这是否是实现此目的的正确方法。有指针,链接或评论吗?

注意:我问是因为向函数添加Lwt_io.read_int(i)是多余的。我可以消除get_int函数,而仅调用Lwt_io.read_int(i),但我很好奇您如何在没有冗余的情况下执行此操作。

ivg*_*ivg 5

首先,让我们切换到新的Lwt术语。根据Lwt库中接受的新术语,该Lwt.wait函数返回一个Promise 和一个resolver。

这是一个非常低级的接口,通常用于实现更多高级接口。实际上,就您而言,该get_int函数可以实现为just Lwt_io.read_int

因此,为了进行实验,让我们实现一些更有意义的东西:

let wait () =
   let promise, resolver = Lwt.wait () in
   Lwt.async (fun () ->
      Lwt_unix.sleep (Random.float 1.0) >|= 
      Lwt.wakeup resolver);
   promise
Run Code Online (Sandbox Code Playgroud)

我们的wait函数返回一个promise,它会在随机延迟后实现。您可能会看到,有一个Lwt.async对它的调用将产生重击,并在事件处理程序中异步执行它,因此函数wait立即返回。当然,此示例没有多大意义,因为具有相同语义的函数可以实现为:

let wait () = Lwt_unix.sleep 1.0
Run Code Online (Sandbox Code Playgroud)

但这仅表明,该wait函数仅用于实现Lwt原语。

该接口的合理使用之一是当您需要分离服务提供者和服务使用者时。然后,您可以使用Lwt.wait(甚至更好Lwt.add_task_*,例如,

module Broker = sig 
  type 'a t
  val request : 'a t -> 'a Lwt.t
  val provide : 'a t -> 'a -> unit
end = struct 
  type 'a t = {mutable requested : 'a Lwt.u option}

  let request broker = 
     let promise, request = Lwt.wait () in
     broker.requested <- Some request;
     promise

  let provide broker data = match broker.requested with
    | None -> ()
    | Some request -> Lwt.wakeup request data
end
Run Code Online (Sandbox Code Playgroud)

当然,我们只是重新实现了邮箱(这又是另一种证明,因为我们已经为我们完成了所有工作,所以通常不需要走低),但是通常,当您有多个请求并且想要实现时您自己安排它们的时间,那么您可以使用此低级界面。