Erlang/OTP如何通知父进程子进程空闲且其邮箱中没有消息

Erlang/OTP如何通知父进程子进程空闲且其邮箱中没有消息,erlang,otp,Erlang,Otp,我想设计一个流程层次结构,其中有一个父流程p,它像一个看门人,将工作(来自其客户端流程的消息/事件)委托给它的子流程C1、C2..Cn,这些子流程相互协作,并可能将结果发送回p。子流程不能与外部的任何流程对话,只有P 挑战在于,尽管p可能有来自其客户端的多条消息,但它应该只接受一条消息,将工作委托给C1..Cn,并且只接受来自其客户端的下一条消息 当它的所有子进程都完成(或空闲)并且不再有消息在C1到Cn之间循环时 P完成接受来自C1..Cn的消息,以便将结果返回给其客户端 限制条件: 空

我想设计一个流程层次结构,其中有一个父流程p,它像一个看门人,将工作(来自其客户端流程的消息/事件)委托给它的子流程C1、C2..Cn,这些子流程相互协作,并可能将结果发送回p。子流程不能与外部的任何流程对话,只有P

挑战在于,尽管p可能有来自其客户端的多条消息,但它应该只接受一条消息,将工作委托给C1..Cn,并且只接受来自其客户端的下一条消息

  • 当它的所有子进程都完成(或空闲)并且不再有消息在C1到Cn之间循环时
  • P完成接受来自C1..Cn的消息,以便将结果返回给其客户端
限制条件:

  • 空闲对我来说是当他们等待接收(阻塞)或只是退出时
  • C1到Cn是有限状态机。它们中的一些或全部可能会将消息发送回C。或者可能没有消息要发送回C。即使没有消息发送回C,C也必须确定它们之间没有消息
  • 如果C1到Cn中的任何一个已经被抢占,那么它被认为是繁忙的(这可能是显而易见的,但我想我会把它放在这里完成),C将不会收到下一条消息
是否有一个OTP模式或库可以为我做到这一点(在我破解某些东西之前?)。我知道
process\u info
可以让我知道进程的邮箱是否为空,我可以继续从P检查孩子们的邮箱,但不必从P进行轮询

编辑概述:我正在尝试在Erlang平台上实现的被动变体。这有“分层过程”或复合过程的概念,它们本身可能包含复合过程,直到我们到达一些实际代码框…我将进行研究(查看监视器、过程信息、过程标志),但我想回应您的优秀答案

编辑递归父进程:C1和Cn各自可以是父进程/复合进程。如果我只是生成进程并让它们立即退出,那么每次我都必须创建复合链,因为C1..Cn本身可能是复合物(生成复合物..等等)。最后,当我们到达一个叶盒(不是复合节点)时,它们应该是有限状态机。。因此,如果是FSM,我不确定产卵和让它们快速退出


编辑TKOWAL:因为我试图创建一个通用的父/复合流程,所以它不知道任务“何时”结束。它所做的只是将从其子级接收到的消息中继到其同级,并带有“约束”,即在其子级“完成”之前,它不会接受来自其客户端/同级的下一条消息。子级C1..Cn可能不仅发送一条消息,还发送多条消息。我从您的建议中了解到,等待任务完成将在收到第一条消息时停止阻止。但P的孩子们也可能发出更多的信息。P应该等待所有消息。同样,有一个任务结束符号也不会因为同样的原因起作用(即可能有多条来自孩子们的消息)

我不认为有现成的库来实现这一点,但它确实很容易破解,除非我错过了什么。您的P过程应该如下所示:

ready_for_next_task() ->
    receive
        {task, Task, CallerPid} ->
            send_task_to_workers(Task)
    end,
    wait_for_task_finish(CallerPid).

wait_for_task_finish(CallerPid) ->
    receive
        {task_end, Response} ->
            CallerPid ! Response
    end,
    ready_for_next_task().
wait\u for\u task\u finish/1
中,您只有一个receive子句,因此它不会接受下一个任务,直到当前任务完成。如果您正在等待工作人员的多个响应,只需将第二个子句添加到带有部分响应的
receive
,然后递归调用
wait\u for\u task\u finish/1

最好有一些指标,即处理结束,因为您没有消息传递时间的保证。这意味着,您可以检查所有进程当前是否正在等待消息,并认为它们已结束处理,但实际上,它们尚未启动,或者其中一个进程向另一个进程发送消息,而您在第二个进程将消息放入消息框之前捕获了它们


如果进程C1..Cn只有部分实际工作,并且不知道进度,那么网守p应该知道有多少部分,一个接一个地接收所有部分,然后调用
ready\u进行下一个任务/1

,因为启动Erlang进程的成本非常低,您的看门人可以为每个传入任务启动新的子任务,然后等待它们完成工作后正常退出


但总的来说,听起来像是在寻找一个进程池。其中有一些已经可用,例如和。池可以是,所以我建议在尝试编写自己的池之前使用现有的经验证的池实现。

编辑后,这变成了一个完全不同的问题,所以我发布了新的答案

若您试图编写基于流的编程,那个么您可能解决了错误的问题。FBP是有效的,因为几乎所有的事情都是异步的,并且您在完成前一个请求后立即开始处理下一个请求

因此,答案是——不要等待孩子们完成:

在FBP中,组件之间没有时间依赖关系。所以如果我 如果有一块数据,它应该能够从数据的一端流动 无论任何其他数据段是如何显示的,都可以将图表转换为其他数据段 正在处理中。为了编程FBP系统,您必须最小化 你的依赖关系

创建父块和子块时,您知道块之间的所有连接,所以只需配置子块,将处理后的数据直接发送到下一个块。例如:P1有子项C1和C2。您将消息发送到P1,它将消息委托给C1,数据包在C1和C2之间流动几次,然后C1或C2将消息直接发送到P2

块应该是无状态的。它们的产出不应依赖于