Erlang/OTP模式,以确保复合进程仅在子进程完成时接受消息

Erlang/OTP模式,以确保复合进程仅在子进程完成时接受消息,erlang,otp,Erlang,Otp,以下问题是否有Erlang/OTP模式/库(在我破解自己的问题之前): 在最高级别,假设有三个组件(或进程?),其中A->B->C其中->表示向发送消息 B在架构方面是一个复合过程。它由许多单元过程组成(如下卡其绿所示)。有时,消息链从B1->B2->B3->C开始,有时从B1->B4->B5->B6->B3->C开始 我想做的是: B只能在其所有子进程完成时接受下一条消息,即B接收到消息I1,并根据消息选择一个流,最后C获得消息O1。在此之前,B不应接受消息I2。这是为了确保消息的顺序

以下问题是否有Erlang/OTP模式/库(在我破解自己的问题之前):

  • 在最高级别,假设有三个组件(或进程?),其中A->B->C其中->表示向发送消息
  • B在架构方面是一个复合过程。它由许多单元过程组成(如下卡其绿所示)。有时,消息链从B1->B2->B3->C开始,有时从B1->B4->B5->B6->B3->C开始

我想做的是:

  • B只能在其所有子进程完成时接受下一条消息,即B接收到消息I1,并根据消息选择一个流,最后C获得消息O1。在此之前,B不应接受消息I2。这是为了确保消息的顺序,以便I2的O2不会在I1的O1之前到达C

    • 这有几个名字。一个是“数据流”(如“反应式编程”——如果你查一下,这是一个夸张的术语球),另一个是“信号模拟”(如电信号开关模拟)。我不知道在Erlang中有这样的框架,因为直接实现它非常简单

      消息排序问题可以自行解决,这取决于您希望如何编写内容。Erlang保证了消息在两个进程之间的顺序,因此只要消息在定义良好的通道中传输,这个系统范围的承诺就可以为您服务。如果您需要一些比直线更有趣的信号路径,您可以强制同步通信;尽管所有的Erlang消息都是异步的,但您可以在
      receive
      上引入同步阻塞

      如果您希望“B星座”将消息传递给C,但仅在其信号处理完成通过B的路由后,您可以创建一个信号管理器,将消息发送到B1,并阻塞,直到收到B3的输出,然后将完成的消息传递给C,并检查其框中是否有来自a的下一件事:

      a_loop(B) ->
        receive {in, Data} -> B ! Data end,
        a_loop(B).
      
      % Note the two receives here -- we are blocking for the end of processing based
      % on the known Ref we send out and expect to receive back in a message match.
      b_manager(B1, C) ->
        Ref = make_ref(),
        receive Data -> B1 ! {Ref, Data} end,
        receive {Ref, Result} -> C ! Result end,
        b_manager(B1, C).
      
      b_1(B2) ->
        receive
          {Ref, Data} ->
              Mod1 = do_processing(Data),
              B2 ! {Ref, Mod1}
        end,
        b_1(B2).
      
      % Here you have as many "b_#" processes as you need...
      
      b_2(B) ->
        receive
          {Ref, Data} ->
              Result = do_other_processing(Data),
              B ! {Ref, Result}
        end,
        b_2(B).
      
      c_loop() ->
        receive Result -> stuff(Result) end,
        c_loop().
      
      很明显,我对事情进行了极大的简化,因为在这篇文章中,显然没有包含任何监管的概念,我甚至没有提到如何将这些联系在一起(通过这个小小的活动性检查,你需要生成链接,这样如果有任何东西死了,它们都会死——这可能正是你想要的B子集,所以你可以把它当作一个单独的单元来对待)。此外,你可能会在某个地方需要一个节流阀(比如在a/之前,或在B中).但基本上说,这是一种传递消息的方式,使B阻塞,直到其处理段完成

      还有其他方法,比如gen_事件,但我发现它们不如编写处理管道的实际模拟灵活。至于如何实现这一点——我将把它变成OTP监控程序和gen_fsm的组合,因为这两个组件代表了信号处理组件的近乎完美的并行,而您的系统似乎是这样的旨在模仿

      为了发现您的gen_FSM中需要哪些状态,以及您希望如何将它们组合在一起,我可能会以非常简单的方式在纯Erlang中进行几个小时的原型制作,以确保我真正理解问题,然后编写适当的OTP主管和gen_FSM。这确保我不会投资于gen_f的某些庙宇面向对象的行为,而不是投资于实际解决我的问题(无论如何,在它正确之前,你必须至少写两次…)


      希望这至少能给您一个开始解决问题的地方。在任何情况下,这在Erlang中都是一种非常自然的事情——并且与语言和问题的工作方式非常接近,应该会非常有趣。

      您正在学习信号模拟:)。它应该是一种面向事件、反应式、基于流的编程,很大程度上受到硬件芯片设计的启发。我想我已经达到了流行语的极限;)。非常感谢!虽然你准确地抓住了我问题的意图,但我觉得我的问题是错误的。我想我在这里制定的更好。我不想改变这个问题,因为你的回答很好。