查看源码 erpc (内核 v10.2)
增强型远程过程调用
此模块提供类似于远程过程调用的服务。远程过程调用是一种在远程节点上调用函数并收集答案的方法。它用于收集远程节点上的信息,或者在远程节点上运行具有某些特定副作用的函数。
这是 rpc
模块提供的操作的增强子集。增强是指它可以区分返回值、引发的异常和其他错误。erpc
也比原始 rpc
实现具有更好的性能和可伸缩性。但是,当前的 rpc
模块将利用 erpc
来尽可能地提供这些属性。
为了使 erpc
操作成功,远程节点也需要支持 erpc
。通常,只有 OTP 23 或更高版本的普通 Erlang 节点才具有 erpc
支持。
请注意,用户有责任确保通过 erpc
执行的正确代码在相关节点上可用。
注意
有关分布式信号的一些重要信息,请参阅 Erlang 参考手册的进程章节中的通过分布的阻塞信号部分。阻塞信号可能会导致
erpc
中的超时显著延迟。
总结
类型
一个不透明的请求标识符。有关更多信息,请参阅 send_request/4
。
一个不透明的请求标识符集合 (request_id/0
),其中每个请求标识符都可以与用户选择的标签关联。有关更多信息,请参阅 reqids_new/0
。
erpc 函数使用的超时时间。
函数
在节点 Node
上评估 apply(Module, Function, Args)
并返回相应的值 Result
。Timeout
设置 call
操作完成的最长时间限制。
在节点 Node
上评估 apply(Module, Function, Args)
。不向调用进程传递响应。cast()
在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。
检查消息是否是对调用进程先前使用 send_request/4
发出的 call
请求的响应。
检查消息是否是对 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
在多个节点上并行执行多个 call
操作。
在节点 Nodes
上评估 apply(Module, Function, Args)
。不向调用进程传递响应。multicast()
在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。
接收对调用进程先前使用 send_request/4
发出的 call
请求的响应。
接收对 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
保存 RequestId
并通过将此信息添加到 RequestIdCollection
并返回生成的请求标识符集合,将 Label
与请求标识符关联。
返回一个新的空请求标识符集合。可以使用请求标识符集合来处理多个未完成的请求。
返回 RequestIdCollection
中保存的请求标识符的数量。
返回一个 {RequestId, Label}
元组的列表,该列表对应于 RequestIdCollection
集合中存在的所有请求标识符及其关联的标签。
向节点 Node
发送异步 call
请求。
向节点 Node
发送异步 call
请求。Label
将与操作的请求标识符关联,并添加到返回的请求标识符集合 NewRequestIdCollection
。稍后可以通过将该集合作为参数传递给 receive_response/3
、wait_response/3
或 check_response/3
来获取集合中与请求对应的响应。
等效于 erpc:wait_response(RequestId, 0)
。也就是说,轮询先前由调用进程发出的 call
请求的响应消息。
等待或轮询先前由调用进程使用 send_request/4
发出的 call
请求的响应消息。
等待或轮询与 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
类型
-opaque request_id()
一个不透明的请求标识符。有关更多信息,请参阅 send_request/4
。
-opaque request_id_collection()
一个不透明的请求标识符集合 (request_id/0
),其中每个请求标识符都可以与用户选择的标签关联。有关更多信息,请参阅 reqids_new/0
。
-type timeout_time() :: 0..4294967295 | infinity | {abs, integer()}.
erpc 函数使用的超时时间。
该值可以是
0..4294967295
- 相对于当前时间的毫秒超时。infinity
- 无限超时。也就是说,操作永远不会超时。{abs, Timeout}
- 绝对 Erlang 单调时间超时,以毫秒为单位。也就是说,当erlang:monotonic_time(millisecond)
返回的值大于或等于Timeout
时,操作将超时。不允许Timeout
识别超过4294967295
毫秒的未来时间。当响应与完整的请求集合 (request_id_collection/0
) 相对应时,使用绝对超时值标识超时尤其方便,因为您不必一遍又一遍地重新计算截止时间之前的相对时间。
函数
-spec call(Node, Fun, Timeout) -> Result when Node :: node(), Fun :: function(), Timeout :: timeout_time(), Result :: term().
等效于 erpc:call(Node, erlang, apply, [Fun,[]], Timeout)
。
可能会引发与 call/5
相同的异常,此外,如果 Fun
不是零元函数,则会引发 {erpc, badarg}
error
异常。
-spec call(Node, Module, Function, Args, Timeout) -> Result when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], Timeout :: timeout_time(), Result :: term().
在节点 Node
上评估 apply(Module, Function, Args)
并返回相应的值 Result
。Timeout
设置 call
操作完成的最长时间限制。
只有当所应用的函数成功返回且没有引发任何未捕获的异常、操作没有超时且没有发生任何故障时,call()
函数才会返回。在所有其他情况下,都会引发异常。以下异常(按异常类列出)目前可以由 call()
引发。
throw
- 所应用的函数调用了throw(Value)
并且没有捕获此异常。异常原因Value
等于传递给throw/1
的参数。exit
- 异常原因{exception, ExitReason}
- 所应用的函数调用了exit(ExitReason)
并且没有捕获此异常。退出原因ExitReason
等于传递给exit/1
的参数。{signal, ExitReason}
- 应用该函数的进程接收到退出信号并因该信号而终止。该进程以退出原因ExitReason
终止。
error
- 异常原因{exception, ErrorReason, StackTrace}
- 在应用函数时发生运行时错误,从而引发错误异常,并且所应用的函数没有捕获该异常。错误原因ErrorReason
指示发生的错误类型。StackTrace
的格式与在try/catch
结构中捕获时相同。StackTrace
仅限于所应用的函数及其调用的函数。{erpc, ERpcErrorReason}
-erpc
操作失败。以下ERpcErrorReason
是最常见的错误原因:badarg
- 如果以下任何一项为真:Node
不是原子。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。Timeout
无效。
noconnection
- 与Node
的连接丢失或无法建立。该函数可能被应用,也可能不被应用。system_limit
- 由于达到某些系统限制,erpc
操作失败。这通常是由于无法在远程节点Node
上创建进程,但也可能是其他原因。timeout
-erpc
操作超时。该函数可能被应用,也可能不被应用。notsup
- 远程节点Node
不支持此erpc
操作。
如果 erpc
操作失败,但不知道该函数是否/将要被应用(即超时或连接丢失),则调用方将不会收到有关所应用函数何时完成的任何进一步信息。如果所应用的函数明确地与调用进程通信,则此类通信当然可以到达调用进程。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是调用进程本身、服务器或新生成的进程。
等效于 erpc:cast(Node,erlang,apply,[Fun,[]])
。
如果出现以下情况,cast/2
会因 {erpc, badarg}
error
异常而失败:
Node
不是原子。Fun
不是零元函数。
-spec cast(Node, Module, Function, Args) -> ok when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()].
在节点 Node
上评估 apply(Module, Function, Args)
。不向调用进程传递响应。cast()
在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。
如果出现以下情况,cast/4
会因 {erpc, badarg}
error
异常而失败:
Node
不是原子。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
-spec check_response(Message, RequestId) -> {response, Result} | no_response when Message :: term(), RequestId :: request_id(), Result :: term().
检查消息是否是对调用进程先前使用 send_request/4
发出的 call
请求的响应。
RequestId
应该是先前 send_request/4
调用返回的值,并且相应的响应不应已由 check_response/2
、receive_response/2
或 wait_response/2
接收并处理完毕。Message
是要检查的消息。
如果 Message
与响应不对应,则返回原子 no_response
。如果 Message
与响应对应,则 call
操作完成,并且返回值将以 {response, Result}
的形式返回,其中 Result
对应于所应用函数返回的值,否则会引发异常。可以引发的异常与 call/4
可以引发的异常相同。也就是说,不会引发 {erpc, timeout}
error
异常。如果/当检测到无效的 RequestId
时,check_response()
将会因 {erpc, badarg}
异常而失败。
如果 erpc
操作失败,但不知道该函数是否/将要被应用(即连接丢失),则调用方将不会收到有关所应用函数何时完成的任何进一步信息。如果所应用的函数明确地与调用进程通信,则此类通信当然可以到达调用进程。
-spec check_response(Message, RequestIdCollection, Delete) -> {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request when Message :: term(), RequestIdCollection :: request_id_collection(), Delete :: boolean(), Result :: term(), Label :: term(), NewRequestIdCollection :: request_id_collection().
检查消息是否是对 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
Label
是与响应对应的请求标识符关联的标签。当在 请求标识符集合 中 添加请求标识符 或使用 send_request/6
发送请求时,请求标识符会与标签关联。
与 check_response/2
相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在 3 元组中。此元组的第一个元素等于 check_response/2
将会生成的值,第二个元素等于与特定请求标识符关联的 Label
,第三个元素 NewRequestIdCollection
是可能已修改的请求标识符集合。error
异常 {erpc, badarg}
与任何特定请求标识符无关,因此不会被包装。
如果 RequestIdCollection
为空,则返回原子 no_request
。如果 Message
与 RequestIdCollection
中的任何请求标识符都不对应,则返回原子 no_response
。
如果 Delete
等于 true
,则与 Label
的关联将已从结果 NewRequestIdCollection
中的 RequestIdCollection
中删除。如果 Delete
等于 false
,则 NewRequestIdCollection
将等于 RequestIdCollection
。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍然可以被后续的 check_response/3
、receive_response/3
和 wait_response/3
调用使用。但是,如果不删除已处理的关联,则以上调用将无法检测到何时没有更多未完成的请求需要处理,因此您必须以其他方式(而不是依赖 no_request
返回值)来跟踪此情况。请注意,如果您传递一个仅包含已处理或放弃的请求的关联的集合给 check_response/3
,它将始终返回 no_response
。
请注意,响应可能在发生 {erpc, badarg}
异常时被使用,如果是这样,则将永远丢失。
-spec multicall(Nodes, Fun, Timeout) -> Result when Nodes :: [atom()], Fun :: function(), Timeout :: timeout_time(), Result :: term().
等效于 erpc:multicall(Nodes, erlang, apply, [Fun,[]], Timeout)
。
可能会引发与 multicall/5
相同的异常,此外,如果 Fun
不是零元函数,则会引发 {erpc, badarg}
error
异常。
-spec multicall(Nodes, Module, Function, Args, Timeout) -> Result when Nodes :: [atom()], Module :: atom(), Function :: atom(), Args :: [term()], Timeout :: timeout_time(), Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].
在多个节点上并行执行多个 call
操作。
也就是说,在节点 Nodes
上并行计算 apply(Module, Function, Args)
。Timeout
设置所有 call
操作完成的上限时间。结果以列表形式返回,其中每个节点的结果与其在 Nodes
中节点名称的位置相同。结果列表中的每个项的格式为:
{ok, Result}
- 此特定节点的call
操作返回Result
。{Class, ExceptionReason}
- 此特定节点的call
操作引发了类Class
的异常,异常原因为ExceptionReason
。这些异常对应于call/5
可以引发的异常。
如果出现以下情况,multicall/5
会因 {erpc, badarg}
error
异常而失败:
Nodes
不是原子的正确列表。请注意,当发生故障时,某些请求可能已经发送。也就是说,该函数可能在某些节点上被应用,也可能不被应用。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。
调用 erpc:multicall(Nodes, Module, Function, Args)
等同于调用 erpc:multicall(Nodes, Module, Function, Args, infinity)
。如果忽略性能和失败行为,这些调用也等同于调用下面的 my_multicall(Nodes, Module, Function, Args)
。multicall()
可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response()
组合无法利用此优化。
my_multicall(Nodes, Module, Function, Args) ->
ReqIds = lists:map(fun (Node) ->
erpc:send_request(Node, Module, Function, Args)
end,
Nodes),
lists:map(fun (ReqId) ->
try
{ok, erpc:receive_response(ReqId, infinity)}
catch
Class:Reason ->
{Class, Reason}
end
end,
ReqIds).
如果 erpc
操作失败,但不知道该函数是否已应用/将要应用(即超时、连接丢失或错误的 Nodes
列表),则调用者将不会收到关于已应用函数完成时的进一步结果信息。当然,如果已应用函数与调用进程通信,则此类通信可能会到达调用进程。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是调用进程本身、服务器或新生成的进程。
等效于 erpc:multicast(Nodes,erlang,apply,[Fun,[]])
。
如果出现以下情况,multicast/2
将失败并抛出 {erpc, badarg}
error
异常:
Nodes
不是原子类型的正确列表。Fun
不是零元函数。
-spec multicast(Nodes, Module, Function, Args) -> ok when Nodes :: [node()], Module :: atom(), Function :: atom(), Args :: [term()].
在节点 Nodes
上评估 apply(Module, Function, Args)
。不向调用进程传递响应。multicast()
在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。
如果出现以下情况,multicast/4
将失败并抛出 {erpc, badarg}
error
异常:
Nodes
不是原子的正确列表。请注意,当发生故障时,某些请求可能已经发送。也就是说,该函数可能在某些节点上被应用,也可能不被应用。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
-spec receive_response(RequestId) -> Result when RequestId :: request_id(), Result :: term().
-spec receive_response(RequestId, Timeout) -> Result when RequestId :: request_id(), Timeout :: timeout_time(), Result :: term().
接收对调用进程先前使用 send_request/4
发出的 call
请求的响应。
RequestId
应该是先前进行的 send_request/4
调用返回的值,并且相应的响应不应已被 receive_response()
、check_response/4
或 wait_response/4
接收和处理完毕。
Timeout
设置等待响应的最长时间限制。如果操作超时,则由 RequestId
标识的请求将被放弃,然后将引发 {erpc, timeout}
error
异常。也就是说,超时后将不会收到与该请求对应的任何响应。如果收到响应,则 call
操作完成,并返回结果或引发异常。可以引发的异常与 call/5
可以引发的异常相同。如果检测到无效的 RequestId
或传递了无效的 Timeout
,则 receive_response/2
将失败并抛出 {erpc, badarg}
异常。
如果忽略性能,则调用下面的函数 my_call(Node, Module, Function, Args, Timeout)
等同于调用 erpc:call(Node, Module, Function, Args, Timeout)
。call()
可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response()
组合无法利用此优化。
my_call(Node, Module, Function, Args, Timeout) ->
RequestId = erpc:send_request(Node, Module, Function, Args),
erpc:receive_response(RequestId, Timeout).
如果 erpc
操作失败,但不知道该函数是否已应用/将要应用(即超时或连接丢失),则调用者将不会收到关于已应用函数完成时的进一步结果信息。当然,如果已应用函数明确与调用进程通信,则此类通信可能会到达调用进程。
-spec receive_response(RequestIdCollection, Timeout, Delete) -> {Result, Label, NewRequestIdCollection} | no_request when RequestIdCollection :: request_id_collection(), Timeout :: timeout_time(), Delete :: boolean(), Result :: term(), Label :: term(), NewRequestIdCollection :: request_id_collection().
接收对 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
Label
是与响应对应的请求标识符关联的标签。当在 请求标识符集合 中 添加请求标识符 或使用 send_request/6
发送请求时,请求标识符会与标签关联。
与 receive_response/2
相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在三元组中。此元组的第一个元素等于 receive_response/2
将会产生的值,第二个元素等于与特定请求标识符关联的 Label
,第三个元素 NewRequestIdCollection
是可能被修改的请求标识符集合。 error
异常 {erpc, badarg}
和 {erpc, timeout}
不与任何特定的请求标识符关联,因此不会被包装。
如果 RequestIdCollection
为空,则将返回原子 no_request
。
如果操作超时,则由 RequestIdCollection
标识的所有请求将被放弃,然后将引发 {erpc, timeout}
error
异常。也就是说,超时后将不会收到与 RequestIdCollection
中的任何请求标识符对应的任何响应。receive_response/3
和 wait_response/3
之间的区别在于,receive_response/3
会在超时时放弃请求,以便忽略任何潜在的未来响应,而 wait_response/3
则不会。
如果 Delete
等于 true
,则与 Label
的关联将已从结果 NewRequestIdCollection
中的 RequestIdCollection
中删除。如果 Delete
等于 false
,则 NewRequestIdCollection
将等于 RequestIdCollection
。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍然可以被后续调用 receive_response/3
、check_response/3
和 wait_response/3
使用。但是,如果不删除已处理的关联,则上述调用将无法检测到何时没有更多待处理请求,因此您必须通过其他方式跟踪此信息,而不是依赖 no_request
返回值。请注意,如果将仅包含已处理或已放弃请求的关联的集合传递给 receive_response/3
,则它将始终阻塞直到触发由 Timeout
确定的超时。
请注意,响应可能在发生 {erpc, badarg}
异常时被使用,如果是这样,则将永远丢失。
-spec reqids_add(RequestId :: request_id(), Label :: term(), RequestIdCollection :: request_id_collection()) -> NewRequestIdCollection :: request_id_collection().
保存 RequestId
并通过将此信息添加到 RequestIdCollection
并返回生成的请求标识符集合,将 Label
与请求标识符关联。
-spec reqids_new() -> NewRequestIdCollection :: request_id_collection().
返回一个新的空请求标识符集合。可以使用请求标识符集合来处理多个未完成的请求。
使用 reqids_add/3
可以将 send_request/4
发出的请求的请求标识符保存在请求标识符集合中。稍后可以通过将该集合作为参数传递给 check_response/3
、receive_response/3
和 wait_response/3
,从而获取该集合中与请求对应的响应。
可以使用 reqids_size/1
确定请求标识符集合中的请求标识符数量。
-spec reqids_size(RequestIdCollection :: request_id_collection()) -> non_neg_integer().
返回 RequestIdCollection
中保存的请求标识符的数量。
-spec reqids_to_list(RequestIdCollection :: request_id_collection()) -> [{RequestId :: request_id(), Label :: term()}].
返回一个 {RequestId, Label}
元组的列表,该列表对应于 RequestIdCollection
集合中存在的所有请求标识符及其关联的标签。
-spec send_request(Node, Fun) -> RequestId when Node :: node(), Fun :: function(), RequestId :: request_id().
等效于 erpc:send_request(Node, erlang, apply, [Fun, []])
。
如果出现以下情况,将失败并抛出 {erpc, badarg}
error
异常:
Node
不是原子。Fun
不是零元函数。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
-spec send_request(Node, Module, Function, Args) -> RequestId when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], RequestId :: request_id(); (Node, Fun, Label, RequestIdCollection) -> NewRequestIdCollection when Node :: node(), Fun :: function(), Label :: term(), RequestIdCollection :: request_id_collection(), NewRequestIdCollection :: request_id_collection().
向节点 Node
发送异步 call
请求。
send_request/4
返回请求标识符,该标识符稍后将传递给 receive_response/2
、wait_response/2
或 check_response/2
,以获取调用请求的响应。除了将请求标识符直接传递给这些函数之外,还可以使用 reqids_add/3
将其添加到请求标识符集合中。稍后可以通过将该集合作为参数传递给 receive_response/3
、wait_response/3
或 check_response/3
,从而获取该集合中与请求对应的响应。如果您要将请求标识符保存在请求标识符集合中,则不妨考虑使用 send_request/6
。
如果忽略性能,则调用下面的函数 my_call(Node, Module, Function, Args, Timeout)
等同于调用 erpc:call(Node, Module, Function, Args, Timeout)
。call()
可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response()
组合无法利用此优化。
my_call(Node, Module, Function, Args, Timeout) ->
RequestId = erpc:send_request(Node, Module, Function, Args),
erpc:receive_response(RequestId, Timeout).
如果出现以下情况,将失败并抛出 {erpc, badarg}
error
异常:
Node
不是原子。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
等同于 erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection)
。
如果出现以下情况,将失败并抛出 {erpc, badarg}
error
异常:
Node
不是原子。Fun
不是零元函数。- 检测到
RequestIdCollection
不是请求标识符集合。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
-spec send_request(Node, Module, Function, Args, Label, RequestIdCollection) -> NewRequestIdCollection when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], Label :: term(), RequestIdCollection :: request_id_collection(), NewRequestIdCollection :: request_id_collection().
向节点 Node
发送异步 call
请求。Label
将与操作的请求标识符关联,并添加到返回的请求标识符集合 NewRequestIdCollection
。稍后可以通过将该集合作为参数传递给 receive_response/3
、wait_response/3
或 check_response/3
来获取集合中与请求对应的响应。
等同于 erpc:reqids_add
(erpc:send_request
(Node, Module, Function, Args), Label, RequestIdCollection)
,但调用 send_request/6
效率稍高。
如果出现以下情况,将失败并抛出 {erpc, badarg}
error
异常:
Node
不是原子。Module
不是原子。Function
不是原子。Args
不是列表。请注意,该列表在客户端未验证为正确列表。- 检测到
RequestIdCollection
不是请求标识符集合。
注意
您不能对将执行
apply()
的进程做出任何假设。它可能是服务器,也可能是新生成的进程。
-spec wait_response(RequestId) -> {response, Result} | no_response when RequestId :: request_id(), Result :: term().
等效于 erpc:wait_response(RequestId, 0)
。也就是说,轮询先前由调用进程发出的 call
请求的响应消息。
-spec wait_response(RequestId, WaitTime) -> {response, Result} | no_response when RequestId :: request_id(), WaitTime :: timeout_time(), Result :: term().
等待或轮询先前由调用进程使用 send_request/4
发出的 call
请求的响应消息。
RequestId
应该是先前进行的 send_request()
调用返回的值,并且相应的响应不应已被 check_response/2
、receive_response/2
或 wait_response()
接收和处理完毕。
WaitTime
设置等待响应的最长时间上限。如果在 WaitTime
超时触发之前没有收到响应,则返回原子 no_response
。可以根据需要多次继续等待响应,直到通过 check_response()
、receive_response()
或 wait_response()
接收并完成响应。如果收到响应,则 call
操作完成,并且要么将结果作为 {response, Result}
返回,其中 Result
对应于应用函数返回的值,要么引发异常。可以引发的异常与 call/4
可以引发的异常相同。也就是说,不会引发 {erpc, timeout}
error
异常。wait_response/2
在检测到无效的 RequestId
或传递了无效的 WaitTime
时,将失败并抛出 {erpc, badarg}
异常。
如果 erpc
操作失败,但不知道函数是否已应用/将要应用(即,等待时间值过大或连接丢失),则调用者不会收到有关应用函数完成时的任何进一步结果信息。如果应用函数显式地与调用进程通信,则此类通信当然可能会到达调用进程。
-spec wait_response(RequestIdCollection, WaitTime, Delete) -> {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request when RequestIdCollection :: request_id_collection(), WaitTime :: timeout_time(), Delete :: boolean(), Label :: term(), NewRequestIdCollection :: request_id_collection(), Result :: term().
等待或轮询与 RequestIdCollection
中保存的请求标识符对应的 call
请求的响应。RequestIdCollection
的所有请求标识符必须对应于使用 send_request/4
或 send_request/6
发出的请求,并且所有请求都必须由调用此函数的进程发出。
Label
是与响应对应的请求标识符关联的标签。当在 请求标识符集合 中 添加请求标识符 或使用 send_request/6
发送请求时,请求标识符会与标签关联。
与 wait_response/2
相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在一个 3 元组中。此元组的第一个元素等于 wait_response/2
将产生的值,第二个元素等于与特定请求标识符关联的 Label
,第三个元素 NewRequestIdCollection
是一个可能已修改的请求标识符集合。error
异常 {erpc, badarg}
不与任何特定请求标识符关联,因此不会被包装。
如果 RequestIdCollection
为空,则返回 no_request
。如果在 WaitTime
超时触发之前没有收到响应,则返回原子 no_response
。可以根据需要多次继续等待响应,直到通过 check_response()
、receive_response()
或 wait_response()
接收并完成响应。receive_response/3
和 wait_response/3
之间的区别在于,receive_response/3
会在超时时放弃请求,以便忽略任何潜在的未来响应,而 wait_response/3
则不会。
如果 Delete
等于 true
,则 Label
的关联将从结果 NewRequestIdCollection
中的 RequestIdCollection
中删除。如果 Delete
等于 false
,则 NewRequestIdCollection
将等于 RequestIdCollection
。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍可用于后续调用 wait_response/3
、check_response/3
和 receive_response/3
。但是,如果不删除已处理的关联,则上述调用将无法检测何时没有更多待处理的请求需要处理,因此您必须以其他方式跟踪此信息,而不是依赖 no_request
返回值。请注意,如果传递仅包含已处理或已放弃请求的关联的集合给 wait_response/3
,它将始终阻塞,直到触发由 WaitTime
确定的超时,然后返回 no_response
。
请注意,响应可能在发生 {erpc, badarg}
异常时被使用,如果是这样,则将永远丢失。