1

我有一个关于 lwt 的等待函数以及如何在我自己的自定义函数中使用它的问题,该函数将返回一个“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()

在上面的函数中,我调用 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) 但我很好奇你将如何在没有冗余的情况下做到这一点。

4

1 回答 1

5

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

这是一个相当低级的接口,通常用于实现更高级的接口。实际上,在您的情况下,该get_int功能可以实现为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

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

let wait () = Lwt_unix.sleep 1.0

但这只是表明,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

当然,我们只是重新实现了邮箱(这是另一个证明,我们通常不需要那么低,因为一切都已经为我们完成了),但一般来说,当您有多个请求并且想要实现时你自己调度它们,那么你可以使用这个低级接口。

于 2017-02-01T18:38:47.953 回答