summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2020-07-30 14:00:31 +0200
committerRickard Green <rickard@erlang.org>2020-11-12 18:19:17 +0100
commit7f4faa03a0fac9e841d16f4e3a47e66a4668b58e (patch)
tree8ec298b22c9ac2e39ba6d23108d3f8402fef3ca5
parent9362aa5e226954ddadcde3bd41c4e0441a4d56c1 (diff)
downloaderlang-7f4faa03a0fac9e841d16f4e3a47e66a4668b58e.tar.gz
Use alias in gen behaviours
-rw-r--r--lib/stdlib/doc/src/gen_event.xml70
-rw-r--r--lib/stdlib/doc/src/gen_server.xml65
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml66
-rw-r--r--lib/stdlib/src/gen.erl81
-rw-r--r--lib/stdlib/src/gen_event.erl13
-rw-r--r--lib/stdlib/src/gen_fsm.erl6
-rw-r--r--lib/stdlib/src/gen_server.erl11
-rw-r--r--lib/stdlib/src/gen_statem.erl30
-rw-r--r--lib/stdlib/src/stdlib.app.src2
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl5
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl6
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl3
-rw-r--r--lib/wx/test/wx_basic_SUITE.erl8
13 files changed, 317 insertions, 49 deletions
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 2ddff240d2..74ae2674ee 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -297,7 +297,7 @@ gen_event:stop -----> Module:terminate/2
<func>
- <name since="OTP-23">check_response(Msg, RequestId) -> Result</name>
+ <name since="OTP 23.0">check_response(Msg, RequestId) -> Result</name>
<fsummary>Check if a message is a reply from a server.</fsummary>
<type>
<v>Msg = term()</v>
@@ -393,9 +393,59 @@ gen_event:stop -----> Module:terminate/2
</desc>
</func>
+ <func>
+ <name since="OTP @OTP-16718@">receive_response(RequestId, Timeout) -> Result</name>
+ <fsummary>Receive for a reply from a server.</fsummary>
+ <type>
+ <v>RequestId = request_id()</v>
+ <v>Reply = term()</v>
+ <v>Timeout = timeout()</v>
+ <v>Result = {reply, Reply} | timeout | {error, Error}</v>
+ <v>Reply = Error = term()</v>
+ </type>
+ <desc>
+ <p>
+ This function is used to receive for a reply of a request made with
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ to the event manager. This function must be called from the same
+ process from which <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ was made.
+ </p>
+ <p>
+ <c>Timeout</c> is an integer greater then or equal to zero
+ that specifies how many milliseconds to wait for an reply, or
+ the atom <c>infinity</c> to wait indefinitely.
+ If no reply is received within the specified
+ time, the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) no response will be received after a timeout. Otherwise,
+ a garbage response might be received at a later time.
+ </p>
+ <p>
+ The return value <c>Reply</c> is defined in the return value
+ of <c>Module:handle_call/3</c>.
+ </p>
+ <p>
+ If the specified event handler is not
+ installed, the function returns <c>{error,bad_module}</c>. If
+ the callback function fails with <c>Reason</c> or returns an
+ unexpected value <c>Term</c>, this function returns
+ <c>{error,{'EXIT',Reason}}</c> or <c>{error,Term}</c>,
+ respectively. If the event manager dies before or during the
+ request this function returns <c>{error,{Reason, EventMgrRef}}</c>.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
+ and <c>receive_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
+ </desc>
+ </func>
<func>
- <name since="OTP-23">send_request(EventMgrRef, Handler, Request) -> RequestId</name>
+ <name since="OTP 23.0">send_request(EventMgrRef, Handler, Request) -> RequestId</name>
<fsummary>Send a request to a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}</v>
@@ -413,8 +463,9 @@ gen_event:stop -----> Module:terminate/2
Sends a request to event handler <c>Handler</c> installed in
event manager <c>EventMgrRef</c> and returns a handle
<c>RequestId</c>. The return value <c>RequestId</c> shall
- later be used with <seemfa marker="#wait_response/2">
- <c>wait_response/2</c></seemfa> or <seemfa
+ later be used with <seemfa marker="#receive_response/2">
+ <c>receive_response/2</c></seemfa>, <seemfa marker="#wait_response/2">
+ <c>wait_response/2</c></seemfa>, or <seemfa
marker="#check_response/2">
<c>check_response/2</c></seemfa> in the same process to
fetch the actual result of the request.
@@ -668,7 +719,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name since="OTP-23">wait_response(RequestId, Timeout) -> Result</name>
+ <name since="OTP 23.0">wait_response(RequestId, Timeout) -> Result</name>
<fsummary>Wait for a reply from a server.</fsummary>
<type>
<v>RequestId = request_id()</v>
@@ -681,7 +732,7 @@ gen_event:stop -----> Module:terminate/2
<p>
This function is used to wait for a reply of a request made with
<seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
- from the event manager. This function must be called from the same
+ to the event manager. This function must be called from the same
process from which <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
was made.
</p>
@@ -707,6 +758,13 @@ gen_event:stop -----> Module:terminate/2
respectively. If the event manager dies before or during the
request this function returns <c>{error,{Reason, EventMgrRef}}</c>.
</p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
+ and <c>wait_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index 4abb91439e..472d77578a 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -346,6 +346,57 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
+ <name since="OTP @OTP-16718@">receive_response(RequestId, Timeout) -> Result</name>
+ <fsummary>Receive for a reply from a server.</fsummary>
+ <type>
+ <v>RequestId = term()</v>
+ <v>Result = {reply, Reply} | timeout | {error, {Reason, ServerRef}}</v>
+ <v>Reply = term()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
+ <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
+ <v>&nbsp;Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
+ </type>
+ <desc>
+ <p>
+ This function is used to receive a reply of a request made with
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ to a <c>gen_server</c> process. This function must be called
+ from the same process from which
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ was made.
+ </p>
+ <p>
+ <c>Timeout</c> is an integer greater then or equal to zero
+ that specifies how many milliseconds to wait for an reply, or
+ the atom <c>infinity</c> to wait indefinitely.
+ If no reply is received within the specified
+ time, the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) no response will be received after a timeout. Otherwise,
+ a garbage response might be received at a later time.
+ </p>
+ <p>
+ The return value <c>Reply</c> is defined in the return value
+ of <c>Module:handle_call/3</c>.
+ </p>
+ <p>
+ The function returns an error if the <c>gen_server</c>
+ dies before or during this request.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
+ and <c>receive_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name since="">reply(Client, Reply) -> ok</name>
<fsummary>Send a reply to a client.</fsummary>
<type>
@@ -368,7 +419,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name since="OTP-23">send_request(ServerRef, Request) -> RequestId</name>
+ <name since="OTP 23.0">send_request(ServerRef, Request) -> RequestId</name>
<fsummary>Sends a request to a generic server.</fsummary>
<type>
<v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
@@ -384,7 +435,8 @@ gen_server:abcast -----> Module:handle_cast/2
Sends a request to the <c>ServerRef</c> of the
<c>gen_server</c> process and returns a handle <c>RequestId</c>.
The return value <c>RequestId</c> shall later be used with
- <seemfa marker="#wait_response/2"> <c>wait_response/2</c></seemfa> or
+ <seemfa marker="#receive_response/2"> <c>receive_response/2</c></seemfa>,
+ <seemfa marker="#wait_response/2"> <c>wait_response/2</c></seemfa>, or
<seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa>
to fetch the actual result of the request.
</p>
@@ -622,7 +674,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name since="OTP-23">wait_response(RequestId, Timeout) -> Result</name>
+ <name since="OTP 23.0">wait_response(RequestId, Timeout) -> Result</name>
<fsummary>Wait for a reply from a server.</fsummary>
<type>
<v>RequestId = term()</v>
@@ -661,6 +713,13 @@ gen_server:abcast -----> Module:handle_cast/2
The function returns an error if the <c>gen_server</c>
dies before or during this request.
</p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
+ and <c>wait_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index fa3f20535d..1d608ad64d 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -1831,6 +1831,53 @@ handle_event(_, _, State, Data) ->
</func>
<func>
+ <name name="receive_response" arity="1" since="OTP @OTP-16718@"/>
+ <name name="receive_response" arity="2" since="OTP @OTP-16718@"/>
+ <fsummary>Receive for a reply from a server.</fsummary>
+ <desc>
+ <p>
+ This function is used to receive for a reply of a request made with
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ to the <c>gen_statem</c> process. This function must be called
+ from the same process from which
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ was made.
+ </p>
+ <p>
+ <c>Timeout</c> is an integer greater then or equal to zero
+ that specifies how many milliseconds to wait for an reply, or
+ the atom <c>infinity</c> to wait indefinitely. Defaults to
+ <c>infinity</c>.
+ If no reply is received within the specified
+ time, the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) no response will be received after a timeout. Otherwise,
+ a garbage response might be received at a later time.
+ </p>
+ <p>
+ The return value <c><anno>Reply</anno></c> is generated when a
+ <seeerl marker="#state callback"><em>state callback</em></seeerl>
+ returns with
+ <c>{reply,From,<anno>Reply</anno>}</c> as one
+ <seetype marker="#action"><c>action()</c></seetype>,
+ and that <c><anno>Reply</anno></c> becomes the return value
+ of this function.
+ </p>
+ <p>
+ The function returns an error if the <c>gen_statem</c>
+ dies before or during this function call.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
+ and <c>receive_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="reply" arity="1" since="OTP 19.0"/>
<name name="reply" arity="2" since="OTP 19.0"/>
<fsummary>Reply to a caller.</fsummary>
@@ -1874,7 +1921,8 @@ handle_event(_, _, State, Data) ->
</p>
<p>
The return value <c><anno>RequestId</anno></c> shall later be used with
- <seemfa marker="#wait_response/2"> <c>wait_response/1,2</c></seemfa> or
+ <seemfa marker="#receive_response/2"> <c>receive_response/1,2</c></seemfa>,
+ <seemfa marker="#wait_response/2"> <c>wait_response/1,2</c></seemfa>, or
<seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa>
to fetch the actual result of the request.
</p>
@@ -1899,7 +1947,8 @@ handle_event(_, _, State, Data) ->
<c>{reply,From,Reply}</c> as one
<seetype marker="#action"><c>action()</c></seetype>,
and that <c>Reply</c> becomes the return value
- of <seemfa marker="#wait_response/2"> <c>wait_response/1,2</c></seemfa> or
+ of <seemfa marker="#receive_response/2"> <c>receive_response/1,2</c></seemfa>,
+ <seemfa marker="#wait_response/2"> <c>wait_response/1,2</c></seemfa>, or
<seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa> function.
</p>
</desc>
@@ -2125,14 +2174,14 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="wait_response" arity="1" since="OTP-23"/>
- <name name="wait_response" arity="2" since="OTP-23"/>
+ <name name="wait_response" arity="1" since="OTP 23.0"/>
+ <name name="wait_response" arity="2" since="OTP 23.0"/>
<fsummary>Wait for a reply from a server.</fsummary>
<desc>
<p>
This function is used to wait for a reply of a request made with
<seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
- from the <c>gen_statem</c> process. This function must be called
+ to the <c>gen_statem</c> process. This function must be called
from the same process from which
<seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
was made.
@@ -2160,6 +2209,13 @@ handle_event(_, _, State, Data) ->
The function returns an error if the <c>gen_statem</c>
dies before or during this function call.
</p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
+ and <c>wait_response()</c> is that <c>receive_response()</c>
+ abandons the request at timeout so that a potential future
+ response is ignored, while <c>wait_response()</c> does not.
+ </p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index be14665d80..b2f2a0ff4e 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -29,7 +29,8 @@
-export([start/5, start/6, debug_options/2, hibernate_after/1,
name/1, unregister_name/1, get_proc_name/1, get_parent/0,
call/3, call/4, reply/2,
- send_request/3, wait_response/2, check_response/2,
+ send_request/3, wait_response/2,
+ receive_response/2, check_response/2,
stop/1, stop/3]).
-export([init_it/6, init_it/7]).
@@ -198,17 +199,41 @@ call(Process, Label, Request, Timeout)
Fun = fun(Pid) -> do_call(Pid, Label, Request, Timeout) end,
do_for_proc(Process, Fun).
-do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false ->
+-dialyzer({no_improper_lists, do_call/4}).
+
+do_call(Process, Label, Request, infinity)
+ when (is_pid(Process)
+ andalso (node(Process) == node()))
+ orelse (element(2, Process) == node()
+ andalso is_atom(element(1, Process))
+ andalso (tuple_size(Process) =:= 2)) ->
Mref = erlang:monitor(process, Process),
+ %% Local without timeout; no need to use alias since we unconditionally
+ %% will wait for either a reply or a down message which corresponds to
+ %% the process being terminated (as opposed to 'noconnection')...
+ Process ! {Label, {self(), Mref}, Request},
+ receive
+ {Mref, Reply} ->
+ erlang:demonitor(Mref, [flush]),
+ {ok, Reply};
+ {'DOWN', Mref, _, _, Reason} ->
+ exit(Reason)
+ end;
+do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false ->
+ Mref = erlang:monitor(process, Process, [{alias,demonitor}]),
+
+ Tag = [alias | Mref],
- %% OTP-21:
- %% Auto-connect is asynchronous. But we still use 'noconnect' to make sure
- %% we send on the monitored connection, and not trigger a new auto-connect.
+ %% OTP-24:
+ %% Using alias to prevent responses after 'noconnection' and timeouts.
+ %% We however still may call nodes responding via process identifier, so
+ %% we still use 'noconnect' on send in order to try to send on the
+ %% monitored connection, and not trigger a new auto-connect.
%%
- erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]),
+ erlang:send(Process, {Label, {self(), Tag}, Request}, [noconnect]),
receive
- {Mref, Reply} ->
+ {[alias | Mref], Reply} ->
erlang:demonitor(Mref, [flush]),
{ok, Reply};
{'DOWN', Mref, _, _, noconnection} ->
@@ -218,7 +243,12 @@ do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false ->
exit(Reason)
after Timeout ->
erlang:demonitor(Mref, [flush]),
- exit(timeout)
+ receive
+ {[alias | Mref], Reply} ->
+ {ok, Reply}
+ after 0 ->
+ exit(timeout)
+ end
end.
get_node(Process) ->
@@ -246,9 +276,11 @@ send_request(Process, Label, Request) ->
Mref
end.
+-dialyzer({no_improper_lists, do_send_request/3}).
+
do_send_request(Process, Label, Request) ->
- Mref = erlang:monitor(process, Process),
- erlang:send(Process, {Label, {self(), {'$gen_request_id', Mref}}, Request}, [noconnect]),
+ Mref = erlang:monitor(process, Process, [{alias, demonitor}]),
+ erlang:send(Process, {Label, {self(), [alias|Mref]}, Request}, [noconnect]),
Mref.
%%
@@ -257,10 +289,9 @@ do_send_request(Process, Label, Request) ->
-spec wait_response(RequestId::request_id(), timeout()) ->
{reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
-wait_response(Mref, Timeout)
- when is_reference(Mref) ->
+wait_response(Mref, Timeout) when is_reference(Mref) ->
receive
- {{'$gen_request_id', Mref}, Reply} ->
+ {[alias|Mref], Reply} ->
erlang:demonitor(Mref, [flush]),
{reply, Reply};
{'DOWN', Mref, _, Object, Reason} ->
@@ -269,12 +300,30 @@ wait_response(Mref, Timeout)
timeout
end.
+-spec receive_response(RequestId::request_id(), timeout()) ->
+ {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
+receive_response(Mref, Timeout) when is_reference(Mref) ->
+ receive
+ {[alias|Mref], Reply} ->
+ erlang:demonitor(Mref, [flush]),
+ {reply, Reply};
+ {'DOWN', Mref, _, Object, Reason} ->
+ {error, {Reason, Object}}
+ after Timeout ->
+ erlang:demonitor(Mref, [flush]),
+ receive
+ {[alias|Mref], Reply} ->
+ {reply, Reply}
+ after 0 ->
+ timeout
+ end
+ end.
+
-spec check_response(RequestId::term(), Key::request_id()) ->
{reply, Reply::term()} | 'no_reply' | {error, {term(), server_ref()}}.
-check_response(Msg, Mref)
- when is_reference(Mref) ->
+check_response(Msg, Mref) when is_reference(Mref) ->
case Msg of
- {{'$gen_request_id', Mref}, Reply} ->
+ {[alias|Mref], Reply} ->
erlang:demonitor(Mref, [flush]),
{reply, Reply};
{'DOWN', Mref, _, Object, Reason} ->
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 8024221cab..0d069119c9 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -43,7 +43,7 @@
notify/2, sync_notify/2,
add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3,
swap_sup_handler/3, which_handlers/1, call/3, call/4,
- send_request/3, wait_response/2, check_response/2,
+ send_request/3, wait_response/2, receive_response/2, check_response/2,
wake_hib/5]).
-export([init_it/6,
@@ -248,6 +248,14 @@ wait_response(RequestId, Timeout) ->
Return -> Return
end.
+-spec receive_response(RequestId::request_id(), timeout()) ->
+ {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), emgr_ref()}}.
+receive_response(RequestId, Timeout) ->
+ case gen:receive_response(RequestId, Timeout) of
+ {reply, {error, _} = Err} -> Err;
+ Return -> Return
+ end.
+
-spec check_response(Msg::term(), RequestId::request_id()) ->
{reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), emgr_ref()}}.
check_response(Msg, RequestId) ->
@@ -396,6 +404,9 @@ terminate_server(Reason, Parent, MSL, ServerName) ->
do_unlink(Parent, MSL),
exit(Reason).
+reply({To, [alias|Alias] = Tag}, Reply) when is_pid(To), is_reference(Alias) ->
+ Alias ! {Tag, Reply},
+ ok;
reply({From, Ref}, Msg) ->
From ! {Ref, Msg},
ok.
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index f4752c37d4..9ff58584eb 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -564,8 +564,12 @@ from({'$gen_sync_all_state_event', From, _Event}) -> From;
from(_) -> undefined.
%% Send a reply to the client.
+reply({To, [alias|Alias] = Tag}, Reply) when is_pid(To), is_reference(Alias) ->
+ Alias ! {Tag, Reply},
+ ok;
reply({To, Tag}, Reply) ->
- catch To ! {Tag, Reply}.
+ catch To ! {Tag, Reply},
+ ok.
reply(Name, From, Reply, Debug, StateName) ->
reply(From, Reply),
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index e49961a5f0..86196eaf2a 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -97,7 +97,8 @@
start_monitor/3, start_monitor/4,
stop/1, stop/3,
call/2, call/3,
- send_request/2, wait_response/2, check_response/2,
+ send_request/2, wait_response/2,
+ receive_response/2, check_response/2,
cast/2, reply/2,
abcast/2, abcast/3,
multi_call/2, multi_call/3, multi_call/4,
@@ -260,6 +261,11 @@ send_request(Name, Request) ->
wait_response(RequestId, Timeout) ->
gen:wait_response(RequestId, Timeout).
+-spec receive_response(RequestId::request_id(), timeout()) ->
+ {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), server_ref()}}.
+receive_response(RequestId, Timeout) ->
+ gen:receive_response(RequestId, Timeout).
+
-spec check_response(Msg::term(), RequestId::request_id()) ->
{reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), server_ref()}}.
check_response(Msg, RequestId) ->
@@ -290,6 +296,9 @@ cast_msg(Request) -> {'$gen_cast',Request}.
%% -----------------------------------------------------------------
%% Send a reply to the client.
%% -----------------------------------------------------------------
+reply({To, [alias|Alias] = Tag}, Reply) when is_pid(To), is_reference(Alias) ->
+ Alias ! {Tag, Reply},
+ ok;
reply({To, Tag}, Reply) ->
catch To ! {Tag, Reply},
ok.
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index adf1a82a08..9b73a919c8 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -32,7 +32,8 @@
start_monitor/3,start_monitor/4,
stop/1,stop/3,
cast/2,call/2,call/3,
- send_request/2,wait_response/1,wait_response/2,check_response/2,
+ send_request/2,wait_response/1,wait_response/2,
+ receive_response/1,receive_response/2,check_response/2,
enter_loop/4,enter_loop/5,enter_loop/6,
reply/1,reply/2]).
@@ -596,6 +597,16 @@ wait_response(RequestId) ->
wait_response(RequestId, Timeout) ->
gen:wait_response(RequestId, Timeout).
+-spec receive_response(RequestId::request_id()) ->
+ {reply, Reply::term()} | {error, {term(), server_ref()}}.
+receive_response(RequestId) ->
+ gen:receive_response(RequestId, infinity).
+
+-spec receive_response(RequestId::request_id(), timeout()) ->
+ {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
+receive_response(RequestId, Timeout) ->
+ gen:receive_response(RequestId, Timeout).
+
-spec check_response(Msg::term(), RequestId::request_id()) ->
{reply, Reply::term()} | 'no_reply' | {error, {term(), server_ref()}}.
check_response(Msg, RequestId) ->
@@ -610,6 +621,9 @@ reply(Replies) when is_list(Replies) ->
%%
-compile({inline, [reply/2]}).
-spec reply(From :: from(), Reply :: term()) -> ok.
+reply({To, [alias|Alias] = Tag}, Reply) when is_pid(To), is_reference(Alias) ->
+ Alias ! {Tag, Reply},
+ ok;
reply({To,Tag}, Reply) when is_pid(To) ->
Msg = {Tag,Reply},
try To ! Msg of
@@ -679,8 +693,22 @@ call_dirty(ServerRef, Request, Timeout, T) ->
Stacktrace)
end.
+call_clean(ServerRef, Request, Timeout, T)
+ when (is_pid(ServerRef)
+ andalso (node(ServerRef) == node()))
+ orelse (element(2, ServerRef) == node()
+ andalso is_atom(element(1, ServerRef))
+ andalso (tuple_size(ServerRef) =:= 2)) ->
+ %% No need to use a proxy locally since we know alias will be
+ %% used as of OTP 24 which will prevent garbage responses...
+ call_dirty(ServerRef, Request, Timeout, T);
call_clean(ServerRef, Request, Timeout, T) ->
%% Call server through proxy process to dodge any late reply
+ %%
+ %% We still need a proxy in the distributed case since we may
+ %% communicate with a node that does not understand aliases.
+ %% This can be removed when alias support is mandatory.
+ %% Probably in OTP 26.
Ref = make_ref(),
Self = self(),
Pid = spawn(
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index b59e3b28c0..60ddb64640 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -109,6 +109,6 @@
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-3.0","kernel-7.0","erts-11.0","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-7.0","erts-@OTP-16718@","crypto-3.3",
"compiler-5.0"]}
]}.
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index 6840184c74..539dbe3edc 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -410,11 +410,6 @@ abnormal1(Config) when is_list(Config) ->
delayed = gen_fsm:sync_send_event(my_fsm, {delayed_answer,1}, 100),
{'EXIT',{timeout,_}} =
(catch gen_fsm:sync_send_event(my_fsm, {delayed_answer,10}, 1)),
- receive
- Msg ->
- %% Ignore the delayed answer from the server.
- io:format("Delayed message: ~p", [Msg])
- end,
[] = get_messages(),
ok.
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index 8015126b0d..c9ebcef188 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -536,11 +536,11 @@ send_request(Config) when is_list(Config) ->
Promise3 = gen_server:send_request(my_test_name, {call_within, 1000}),
no_reply = gen_server:check_response({foo, bar}, Promise3),
- receive {{'$gen_request_id',Ref},_} = Msg when is_reference(Ref) ->
+ receive {[alias|Ref],_} = Msg when is_reference(Ref) ->
{reply, ok} = gen_server:check_response(Msg, Promise3)
after 1000 ->
- %% Format not yet doumented so it might be ok
- %% This test is just to make you aware that you have changed it
+ %% Format changed which is ok. This test is just to make you
+ %% aware that you have changed it
exit(message_format_changed)
end,
timer:sleep(1500),
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 76dee868e9..16763ce0f9 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -582,8 +582,7 @@ abnormal1dirty(Config) ->
ok = gen_statem:stop(Name),
?t:sleep(1100),
case flush() of
- [{Ref,delayed}] when is_reference(Ref) ->
- ok
+ [] -> ok
end.
%% Check that bad return values makes the stm crash. Note that we must
diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl
index 433b705673..8d77c42e8c 100644
--- a/lib/wx/test/wx_basic_SUITE.erl
+++ b/lib/wx/test/wx_basic_SUITE.erl
@@ -395,13 +395,13 @@ wx_object(Config) ->
?m(false, wxWindow:getParent(Panel) =:= Frame),
?m(true, wx:equal(wxWindow:getParent(Panel),Frame)),
flush(),
- ReqId = wx_object:send_request(Frame, fun(_US) -> timer:sleep(10), yes end),
+ ReqId = wx_object:send_request(Frame, fun(_US) -> timer:sleep(10), yes1 end),
timeout = wx_object:wait_response(ReqId, 0),
- {reply, {call, yes, {Me,{_,ReqId}}}} = wx_object:wait_response(ReqId, 1000),
- ReqId2 = wx_object:send_request(Frame, yes),
+ {reply, {call, yes1, {Me,_}}} = wx_object:wait_response(ReqId, 1000),
+ ReqId2 = wx_object:send_request(Frame, yes2),
[Msg] = flush(),
no_reply = wx_object:check_response(Msg, ReqId),
- {reply, {call, yes, {Me,{_,ReqId2}}}} = wx_object:check_response(Msg, ReqId2),
+ {reply, {call, yes2, {Me,_}}} = wx_object:check_response(Msg, ReqId2),
FramePid = wx_object:get_pid(Frame),
io:format("wx_object pid ~p~n",[FramePid]),