Here's an example that demonstrates that Wotek Surowka's answer is correct:
-module(s1).
-behavior(gen_server).
-compile(export_all).
start() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE,
[],
[]
).
init(_Args) ->
Count = 0,
{ok, Count}.
handle_call(_Msg, _From, State) ->
{reply, hello, State}.
handle_cast(_Msg, Count) ->
io:format("Entered handle_cast()...~n"),
self() ! hello,
timer:sleep(10000), % Sleep for 10 seconds
io:format("Returning from handle_cast()...~n"),
{noreply, Count+1}.
handle_info(Msg, Count) ->
io:format("Entered handle_info(), Msg= ~w~n", [Msg]),
io:format("Count in handle_info() is: ~w~n", [Count]),
io:format("Returning from handle_info()...~n"),
{noreply, Count}.
go() ->
spawn(
fun() -> gen_server:cast(?MODULE, "some message") end
),
ok.
In the example above, handle_cast()
sleeps for 10 seconds, so if handle_info()
executed asynchronously, it would have plenty of time to display its output before handle_cast()
returned. Here are the results in the shell:
~/erlang_programs/gen_s/1server$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(s1).
s1.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,s1}
2> s1:start().
{ok,<0.71.0>}
3> s1:go().
Entered handle_cast()...
ok <--- return value of go()
Returning from handle_cast()...
Entered handle_info(), Msg= hello
Count in handle_info() is: 1
Returning from handle_info()...
4>
The output shows that handle_info()
doesn't begin executing until after handle_cast()
returns.
And, if you add some print statements to display the pid
inside handle_cast()
and handle_info()
, you will see that the pid is the same:
-module(s1).
-behavior(gen_server).
-compile(export_all).
start() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE,
[],
[]
).
init(_Args) ->
Count = 0,
{ok, Count}.
handle_call(_Msg, _From, State) ->
{reply, hello, State}.
handle_cast(_Msg, Count) ->
io:format("Entered handle_cast()...~n"),
Self = self(),
io:format("self() is: ~w~n", [Self]),
Self ! hello,
timer:sleep(10000), % Sleep for 10 seconds
io:format("Returning from handle_cast()...~n"),
{noreply, Count+1}.
handle_info(Msg, Count) ->
io:format("Entered handle_info(), Msg= ~w~n", [Msg]),
io:format("self() is: ~w~n", [self()]),
io:format("Count in handle_info() is: ~w~n", [Count]),
io:format("Returning from handle_info()...~n"),
{noreply, Count}.
go() ->
spawn(
fun() -> gen_server:cast(?MODULE, "some message") end
),
ok.
In the shell:
1> c(s1).
s1.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,s1}
2> s1:start().
{ok,<0.71.0>}
3> s1:go().
Entered handle_cast()...
ok <---return value of go()
self() is: <0.71.0>
Returning from handle_cast()...
Entered handle_info(), Msg= hello
self() is: <0.71.0>
Count in handle_info() is: 1
Returning from handle_info()...
4>