是否可以阻止 Erlang 进程传递消息?

问题描述 投票:0回答:1

在 Erlang 中模拟同步通信有一个非常常见的技巧:

%% Process 'sender'
Ref = make_ref(),
'receiver' ! {self(), Ref, Message},
receive {ack, Ref} -> ok end,
...


%% Process 'receiver'
receive
    {From, Ref, Message} ->
         From ! {ack, Ref},
         handle_msg(Message),
         ...
end

这让

sender
阻塞,直到
receiver
收到消息。然而,我正在寻找的是阻塞直到消息被“传递”,或者换句话说,直到消息进入接收进程的消息队列。重要性在于,我想将其与已经排队的消息顺序的假设结合起来,而不必等待从队列中选取消息(它甚至可能永远不会被选取,我不在乎) . 例如,给定:

%% Process 'sender' send_deliver('receiver', first), 'proxy' ! second %% Process 'receiver' receive unlock -> ok end, receive X -> X end %% Process 'proxy' receive X -> 'receiver' ! X end %% Process 'unlocker' timer:sleep(thousand_years()), 'receiver' ! unlock

我在这个例子中的目标是:

    receiver
  • 必须
    first
    之前收到
    second
    消息有效负载应该是无关紧要的(例如,如果您翻转 
  • first
  • second
    ,则必须首先接收
    second
  • sender
  • 在对
    send_deliver/2
    的调用上被阻塞多长时间不应该取决于
    receiver
    正在做什么(特别是,不应该强迫它等待
    thousand_years
    我可以用元组包装消息并添加附加信息,就像同步发送技巧一样
  • 另外,我普遍希望保留所有消息过滤功能以及有关消息排序的所有假设。 Erlang 中是否有一些内置的技巧或允许我模拟这些语义的模式?

concurrency erlang message-queue
1个回答
0
投票

在底层,它使用锁在本地进程之间传递消息,但一旦跨越节点边界,你就只能靠自己了。我会避免依赖不能保证保持不变的内部实现。

关于你的问题,当我遇到这个问题时,我所做的只是将

second

消息视为

first+second
并为接收者准备好接收无序接收的
first
消息:
receiver() ->
  receive
    first ->
      do_first(),
      receive second -> do_second() end,
    second -> do_first(), do_second(), receive first -> ok end end
  end.

在此解决方案中,由您决定如何处理无序的 
first

消息。您可以使用

reference()
来匹配
first
second
对,使用别名来停用接收器等...
另一个选项是使消息流线性:

Sender -> Proxy -> Receiver

,其中

first
second
消息由代理发送
    

© www.soinside.com 2019 - 2024. All rights reserved.