Asynchronous function calling in Erlang
intro
Thanks to nox
from freenode/#erlang i stumbled about erlfu today.
First I thought that futures (for example: python-futures) in erlang makes sense, but now I am not so sure anymore.
Why did I never have the need for such libraries? Either my use-case or environment was too complex, so I was most likely in a supervisor tree. Here I can spawn my tasks via a simple one for one supervisors and don’t really have to think about what happens to my processes and get answers whenever.
The other possibility is that my calls are simple, then i can just use one of the following possibilities.
simple implementations
simple async function
To implement a simple asynchronous action you can just use fun
and spawn/1
:
spawn(fun() -> timer:sleep(2000), boom end).
callable sync function
via messages
If we want to read a return value it gets a bit trickier. We can use Erlang’s Messages to get it though:
-module(simple_future).
-export([bomb/1]).
bomb(Pid) ->
timer:sleep(2000),
Pid ! {self(), boom}.
29> spawn(simple_future, bomb, [self()]).
<0.83.0>
30> flush().
ok
31> flush().
Shell got {<0.83.0>,boom}
ok
via trap_exit
Another approach would be to trap exits of your spawned processes:
17> process_flag(trap_exit, true).
false
18> spawn_link(fun() -> timer:sleep(2000), exit(boom) end).
<0.66.0>
19> flush().
Shell got {'EXIT',<0.66.0>,boom}
rpc:async_call
Using rpc is surely the most sophisticated approach.
async_call/4
is exactly what we want:
-module(simple_future).
-export([rpcbomb/0]).
rpcbomb() ->
timer:sleep(2000),
boom.
10> Key = rpc:async_call(node(), simple_future, rpcbomb, []).
<0.57.0>
11> rpc:nb_yield(Key, 5000).
{value,boom}
conclusion
Not really sure where I wanted to go with this post.
On one hand I wanted to highlight how great Erlang is at this kind of stuff. You never really wish for a library to do such tasks because it is intuitively possible without a lot of trouble.
On the other hand I don’t want to bash erlfu. It probably has it’s uses though I can not come up with any that rpc could not handle.