是否存在针对以下问题的Erlang / OTP模式/库(在我自己破解之前):
我想做的是:
答案 0 :(得分:2)
这有几个名字。一个是“数据流”(如“反应式编程” - 如果你查找它就是一种夸张的流行语球),另一个是“信号模拟”(如电信号开关的模拟)。我不知道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_event,但我发现它们比编写处理管道的实际模拟更不灵活。至于如何实现这一点 - 我将它作为OTP主管和gen_fsm的组合,因为这两个组件代表了几乎完美的信号处理组件并行,您的系统似乎旨在模仿。
要了解gen_fsms中需要的状态以及如何将它们聚集在一起我可能会在纯粹的Erlang中以非常简单的方式原型化几个小时,以确保我实际上了解问题,然后编写我正确的OTP主管和gen_fsms。这确保我不会投入一些gen_foo行为的神殿,而不是投入实际解决我的问题(你必须在正确之前至少写两次.. )。
希望这至少给你一个开始解决问题的地方。无论如何,这在Erlang中是一种非常自然的事情 - 并且与语言和问题的工作方式非常接近,以至于它应该非常有趣。