{"id":598,"date":"2011-05-09T19:30:40","date_gmt":"2011-05-09T18:30:40","guid":{"rendered":"http:\/\/trigonakis.com\/blog\/?p=598"},"modified":"2011-05-16T08:14:41","modified_gmt":"2011-05-16T07:14:41","slug":"introduction-to-erlang-concurrency-processes","status":"publish","type":"post","link":"http:\/\/trigonakis.com\/blog\/2011\/05\/09\/introduction-to-erlang-concurrency-processes\/","title":{"rendered":"Introduction to Erlang : Concurrency (Processes)"},"content":{"rendered":"<div class=\"seriesmeta\">This entry is part 14 of 16 in the series <a href=\"http:\/\/trigonakis.com\/blog\/series\/introduction-to-erlang\/\" class=\"series-57\" title=\"Introduction to Erlang\">Introduction to Erlang<\/a><\/div><h3>Concurrency<\/h3>\n<p><i>Concurrency<\/i> is defined as <i>&#8220;the temporal property of two things happening at the same time&#8221;<\/i> (according to WordNet). In Computer Science, the definition is <i>&#8220;concurrency is a property of systems in which several computations are executing simultaneously, and potentially interacting with each other. The computations may be executing on multiple cores in the same chip, preemptively time-shared threads on the same processor, or executed on physically separated processors.&#8221;<\/i> (according to <a href=\"https:\/\/secure.wikimedia.org\/wikipedia\/en\/wiki\/Concurrency_(computer_science)\" target=\"_new\">Wikipedia<\/a>).<\/p>\n<p>In practise, if two, or more, tasks are concurrent, then they can run in parallel. This implies that there are no <strong>data dependencies<\/strong> among them. For example, the following tasks<\/p>\n<ul>\n<li>unlock the car (the car was locked)<\/li>\n<li>start the engine of the car (the engine was off)<\/li>\n<li>drive the car<\/li>\n<\/ul>\n<p>are non-concurrent since they have dependencies. One cannot start the engine of the car without first entering the car and she cannot drive it without first starting the engine. These tasks have to be executed sequentially (with a predefined order) no matter if more than one person (processing unit) help. On the other hand<\/p>\n<ul>\n<li>doing the laundry<\/li>\n<li>washing the dishes<\/li>\n<li>go for shopping<\/li>\n<\/ul>\n<p>can be potentially run in parallel. For example, three different family members can handle one task each. Moreover, if only one person has to do all the tasks, she can decide to perform them <strong>in any order she decides<\/strong> since there are no dependencies among them.<br \/>\n<!--more--><\/p>\n<h3>Concurrency in Erlang<\/h3>\n<p>Erlang was built with concurrency and fault-tolerance in mind. <\/p>\n<h4>Processes<\/h4>\n<p>The granularity of concurrency in Erlang is a <strong>process<\/strong>. A process is an activity\/task that runs concurrently with and independently from the other processes (though processes can interact with each other using messages, links, etc. as you shall see later). Processes in Erlang are different than the processes and threads most people are familiar with. Erlang processes are lightweight, operate in (memory) isolation from other processes, and are scheduled by the Erlang&#8217;s Virtual Machine (VM). The creation time of process is very low, the memory footprint of a just spawned process is very small, and a single Erlang VM can have millions of processes running.<\/p>\n<h4>Messaging Passing<\/h4>\n<p>The communication model (among processes) in Erlang is <i>message passing<\/i>. No much need to be said about this. Erlang processes <strong>share no memory<\/strong>. The way that processes communicate is via (asynchronous) message passing. Every process (even the shell) holds a mailbox queue where incoming messages are placed until received by the process. Message passing is asynchronous because the sending process does not block on send. Sending a message in Erlang is a non-blocking operation that always succeed (more in the next post).<\/p>\n<h5>Why Message Passing?<\/h5>\n<p>But why message passing? We are so used to the shared memory model, why changing it?<\/p>\n<p>Here are some characteristics that are part of Erlang mostly because of the message passing memory model.<\/p>\n<h6>Memory independency<\/h6>\n<p>While executing, no shared memory among processes means that there is no chance that a process will cause a memory corruption to another process. The programmer does not have to worry about data races, data corruption, memory synhronization, etc.<\/p>\n<h6>Crash independency<\/h6>\n<p>Processes do not share anything. As a result, the failure (crash) of a process cannot affect another. This is very helpful when builting fault-tolerant and reliable systems (most of the &#8220;real-world&#8221; systems). Due to this, Erlang inherits the &#8220;let it fail&#8221; programming approach; if something &#8220;bad&#8221; happens, let the process fail and handle the process failure instead.<\/p>\n<h6>Distributed programming<\/h6>\n<p>Message passing allows for easier distributed programming. Imagine if you want to distribute an application that uses shared memory. To do this, one should either use a message passing solution (such as MPI) or a Distributed Shared Memory system (DSM), that also uses message passing to operate. Why not using message passing in the first place? Especially in Erlang, message passing allows for <i>location transparency<\/i> (when sending a message there is no difference to the programmer if the receiver resides in the local or a remote node).<\/p>\n<h4>Creating Processes<\/h4>\n<p>Erlang provides Built-In Functions (BIFs) that are used to spawn new processes. The simplest one is <code>spawn\/1|3<\/code> (the <code>1|3<\/code> denotes that both <code>spawn\/1<\/code> and <code>spawn\/3<\/code> functions exist).<\/p>\n<h5>pid Datatype<\/h5>\n<p><code>pid<\/code> stands for <i>Process identifier<\/i> and is the datatype used for the unique process identifiers that are assigned to every process.<\/p>\n<h5>spawn\/1|3<\/h5>\n<p>Creates a new process and returns its <code>pid<\/code>. The new process is placed in the system scheduler queue, so it will be run some time later.<\/p>\n<h6>spawn\/1<\/h6>\n<p>Called as <code>spawn(Fun)<\/code>. The new process will run function <code>Fun<\/code> with an empty list (<code>[]<\/code>) as input.<\/p>\n<h6>spawn\/3<\/h6>\n<p>Called as <code>spawn(Module, Function, Args)<\/code>. The new process will run function <code>Module:Function<\/code> with the elements of the list <code>Args<\/code> as input.<\/p>\n<h6>Examples<\/h6>\n<pre lang=\"erlang\">\r\nprint() ->\r\n    io:format(\"I am process ~w~n\", [self()]).\r\nprint(I) ->\r\n    io:format(\"I am process ~w~n\", [I]).\r\n\r\nspawnPrint() ->\r\n    spawn(?MODULE, print, []).\r\n%or spawn(fun print\/0).\r\n\r\nspawnPrintN(0) ->\r\n    done;\r\nspawnPrintN(N) when is_integer(N), N > 0 ->\r\n    spawn(?MODULE, print, [N]),\r\n    spawnPrintN(N - 1).\r\n\r\nspawnSpawn(0) ->\r\n    io:format(\"I am a 'lief'!~n\"),\r\n    done;\r\nspawnSpawn(N) when is_integer(N), N > 0 ->\r\n    spawn(?MODULE, spawnSpawn, [N - 1]),\r\n    spawnSpawn(N - 1).\r\n\r\nspawnSlashOneA() ->\r\n    spawn(fun print\/0).\r\n\r\n% spawning an anonynous function\r\nspawnSlashOneB() ->\r\n    spawn(fun() -> io:format(\"I am a process ~w~n!\", [self()]) end).\r\n\r\nspawnSort(List) ->\r\n    {Even, Odd} = lists:partition(fun(I) -> I rem 2 == 0 end, List),\r\n    spawn(?MODULE, sortPrint, [\"Even\", Even]),\r\n    spawn(?MODULE, sortPrint, [\"Odd\", Odd]).\r\n\r\nsortPrint(Print, List) ->\r\n    io:format(\"~p sorted: ~w~n\", [Print, lists:sort(List)]).\r\n\r\n% run\r\n1> c(spawning).\r\n{ok,spawning}\r\n2> spawning:spawnPrint().\r\nI am process <0.42.0>\r\n<0.42.0>\r\n3> spawning:spawnPrintN(3).\r\nI am process 3\r\nI am process 2\r\nI am process 1\r\ndone\r\n4> spawning:spawnSpawn(3).\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\nI am a 'lief'!\r\ndone\r\n5> spawning:spawnSlashOneA().\r\nI am process <0.58.0>\r\n<0.58.0>\r\n6> spawning:spawnSlashOneB().\r\nI am a process <0.60.0>\r\n<0.60.0>\r\n7> spawning:spawnSort([4,6,3,7,9,8,2,1]).\r\n\"Even\" sorted: [2,4,6,8]\r\n\"Odd\" sorted: [1,3,7,9]\r\n<0.63.0>\r\n<\/pre>\n<h4>Creating Linked Processes<\/h4>\n<p>A very useful feature is to create a new process that is linked to the &#8220;parent&#8221; one. The link between them guarantees that if one of the two fails (finishes abnormally), the other one also stops executing (an <code>'EXIT'<\/code> signal is propagated). This feature is very helpful because it reduces the need for &#8220;cleaning up&#8221; in case of a failure. Instead of explicitely handling an error, the &#8220;let it fail and let someone else handle it&#8221; philosophy can be used. The BIF(s) providing this functionality are the <code>spawn_link\/1|3<\/code>.<\/p>\n<p>Notice that linking can be done later, between two already running processes, using the BIF <code>link\/1<\/code>. The difference is that the <code>spawn_link<\/code> executes spawning and linking atomically (either both operations succeed, or both fail).<\/p>\n<h5>link\/1<\/h5>\n<p>Creates a bidirectional link between the calling process and another process (or port), if there is not such a link already. If a process attempts to create a link to itself, nothing is done. Returns true.<\/p>\n<h5>spawn_link\/1|3<\/h5>\n<p>Provides the same functionality as <code>spawn\/1|3<\/code> with the addition that <strong>a link is atomically created<\/strong> between the caller and the newly spawned process.<\/p>\n<h6>spawn_link\/1<\/h6>\n<p>Same call convention as <code>spawn\/1<\/code>.<\/p>\n<h6>spawn_link\/3<\/h6>\n<p>Same call convention as <code>spawn\/3<\/code>.<\/p>\n<h6>Examples<\/h6>\n<pre lang=\"erlang\">\r\nspawnLink() ->\r\n    spawn(fun spawnLink_\/0).\r\n\r\nspawnLink_() ->\r\n    spawn_link(?MODULE, abnormalExit, []),\r\n    justLoop().\r\n\r\njustLoop() ->\r\n    justLoop().\r\n\r\nabnormalExit() ->\r\n    timer:sleep(4000),\r\n    erlang:kill(not_catched).\r\n\r\n% run\r\n1> c(spawning).\r\n{ok,spawning}\r\n2> Pid = spawning:spawnLink().  \r\n<0.42.0>\r\n3> erlang:is_process_alive(Pid).\r\ntrue\r\n4> erlang:is_process_alive(Pid).\r\ntrue\r\n5> erlang:is_process_alive(Pid).\r\n=ERROR REPORT==== 7-May-2011::12:24:54 ===\r\nError in process <0.43.0> with exit value: {undef,[{erlang,kill,[not_\r\nfalse\r\n6> erlang:is_process_alive(Pid).\r\nfalse\r\n<\/pre>\n<h4>Other Processes&#8217;-related BIFs<\/h4>\n<p>There are several other BIFs related to processes. The following are some commonly used.<\/p>\n<h5>error\/1<\/h5>\n<p>Called as <code>error(Reason)<\/code>. Stops the execution of the calling process with the reason <code>Reason<\/code>, where <code>Reason<\/code> is any term. The actual exit reason will be <code>{Reason, Where}<\/code>, where <code>Where<\/code> is a list of the functions most recently called (the current function first). Since evaluating this function causes the process to terminate, it has no return value.<\/p>\n<h5>exit\/1|2<\/h5>\n<p>Called as <code>exit(Reason)<\/code>. Stops the execution of the calling process with the exit reason <code>Reason<\/code>, where <code>Reason<\/code> is any term. Since evaluating this function causes the process to terminate, it has no return value.<\/p>\n<p><code>exit\/2<\/code> is called as <code>exit(Pid, Reason)<\/code>. Sends an exit signal with exit reason <code>Reason<\/code> to the process <code>Pid<\/code>.<\/p>\n<p>The following behavior apply if <code>Reason<\/code> is any term except normal or kill:<\/p>\n<p>If <code>Pid<\/code> is not trapping exits, <code>Pid<\/code> itself will exit with exit reason <code>Reason<\/code>. If <code>Pid<\/code> is trapping exits, the exit signal is transformed into a message <code>{'EXIT', From, Reason}<\/code> and delivered to the message queue of <code>Pid<\/code>. From is the pid of the process which sent the exit signal. <\/p>\n<p>If Reason is the atom normal, <code>Pid<\/code> will not exit. If it is trapping exits, the exit signal is transformed into a message <code>{'EXIT', From, normal}<\/code> and delivered to its message queue.<\/p>\n<p>If <code>Reason<\/code> is the atom kill, that is if exit(<code>Pid<\/code>, kill) is called, an untrappable exit signal is sent to <code>Pid<\/code> which will unconditionally exit with exit reason killed.<\/p>\n<pre lang=\"erlang\">\r\n1> Rec = fun(F) -> F(F) end.\r\n#Fun<erl_eval.6.13229925>\r\n2> Loop = fun() -> Rec(Rec) end.\r\n#Fun<erl_eval.20.67289768>\r\n3> Pid = spawn(Loop).\r\n<0.39.0>\r\n4> erlang:is_process_alive(Pid).\r\ntrue\r\n5> exit(Pid, no_reason).\r\ntrue\r\n6> erlang:is_process_alive(Pid).\r\nfalse\r\n<\/pre>\n<h5>is_pid\/1<\/h5>\n<p>Returns true if the argument is a pid, else false.<\/p>\n<pre lang=\"erlang\">\r\n1> Pid = spawn(io, format, [\"Hej~n\"]).\r\nHej\r\n<0.37.0>\r\n2> is_pid(Pid).\r\ntrue\r\n<\/pre>\n<h5>is_process_alive\/1<\/h5>\n<p>Called as <code>is_process_alive(Pid)<\/code>. <code>Pid<\/code> must refer to a process at the local node. Returns true if the process exists and is alive, that is, is not exiting and has not exited. Otherwise, returns false.<\/p>\n<pre lang=\"erlang\">\r\n13> is_process_alive(self()).\r\ntrue\r\n<\/pre>\n<h5>list_to_pid\/1<\/h5>\n<p>Transforms the input string to a pid. This BIF is intended to be used for debugging and not in application development.<\/p>\n<pre lang=\"erlang\">\r\n4> Pid == list_to_pid(\"<0.37.0>\").\r\ntrue\r\n<\/pre>\n<h5>pid_to_list\/1<\/h5>\n<p>Returns the textual representation of a pid. Again, this BIF is intended to be used for debugging only.<\/p>\n<pre lang=\"erlang\">\r\n3> StringPid = pid_to_list(Pid).\r\n\"<0.37.0>\"\r\n<\/pre>\n<h5>register\/2<\/h5>\n<p>Registers a process (or a port) with a name. This name can be later used to refer to the process.<\/p>\n<pre lang=\"erlang\">\r\n7> ShellPid = self().         \r\n<0.44.0>\r\n8> register(shell, ShellPid).\r\ntrue\r\n<\/pre>\n<h5>registered\/0<\/h5>\n<p>Returns a list with the names of all registered processes.<\/p>\n<pre lang=\"erlang\">\r\n9> registered().\r\n[init,shell,error_logger,rex,kernel_sup,inet_db,\r\n global_name_server,file_server_2,code_server,\r\n erl_prim_loader,user_drv,standard_error_sup,\r\n application_controller,standard_error,kernel_safe_sup,user,\r\n global_group]\r\n<\/pre>\n<h5>self\/0<\/h5>\n<p>One of the most commonly used BIF, returns the pid of the calling processes. As you will see in the next post (about messaging), <code>self<\/code> is used in almost every message send.<\/p>\n<pre lang=\"erlang\">\r\n7> ShellPid = self().         \r\n<0.44.0>\r\n<\/pre>\n<h5>erlang:send\/2|3<\/h5>\n<p>Sends a message to a process. We will see message sending in detail in the next post.<\/p>\n<h5>erlang:send_after\/3<\/h5>\n<p>Sends a message after a given amount of time.<\/p>\n<h5>throw\/1<\/h5>\n<p>Called as <code>throw(Any)<\/code>. A non-local return from a function. If evaluated within a catch, catch will return the value <code>Any<\/code>.<\/p>\n<pre lang=\"erlang\">\r\n1> throw(noooooo).                      \r\n** exception throw: noooooo\r\n2> try throw(yeeees) catch _:_ -> ok end.\r\nok\r\n3> catch throw(yeeees).\r\nyeeees\r\n<\/pre>\n<h5>unlink\/1<\/h5>\n<p>Removes the link between two processes. Returns true even if there exist no link.<\/p>\n<h5>unregister\/1<\/h5>\n<p>Called as <code>unregister(Name)<\/code>. Removes the association between the <code>Name<\/code> and the process which it is associated with.<\/p>\n<pre lang=\"erlang\">\r\n11> unregister(shell).\r\ntrue\r\n12> registered().\r\n[init,error_logger,rex,kernel_sup,inet_db,\r\n global_name_server,file_server_2,code_server,\r\n erl_prim_loader,user_drv,standard_error_sup,\r\n application_controller,standard_error,kernel_safe_sup,user,\r\n global_group]\r\n<\/pre>\n<h5>whereis\/1<\/h5>\n<p>Called as <code>whereis(Name)<\/code>. Returns the pid of the process that is register with the name <code>Name<\/code>.<\/p>\n<pre lang=\"erlang\">\r\n10> whereis(shell).\r\n<0.44.0>\r\n<\/pre>\n<h3>Next<\/h3>\n<p>Next post will be about <strong>message passing<\/strong>. After this post one should be able to unveil the &#8220;power of Erlang&#8221;.<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">This entry is part 14 of 16 in the series <a href=\"http:\/\/trigonakis.com\/blog\/series\/introduction-to-erlang\/\" class=\"series-57\" title=\"Introduction to Erlang\">Introduction to Erlang<\/a><\/div><p>Concurrency Concurrency is defined as &#8220;the temporal property of two things happening at the same time&#8221; (according to WordNet). In Computer Science, the definition is &#8220;concurrency is a property of systems in which several computations are executing simultaneously, and potentially interacting with each other. The computations may be executing on multiple cores in the same [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[40,51,28],"tags":[70,26,42],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p1ouW6-9E","_links":{"self":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/598"}],"collection":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/comments?post=598"}],"version-history":[{"count":10,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/598\/revisions"}],"predecessor-version":[{"id":609,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/598\/revisions\/609"}],"wp:attachment":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/media?parent=598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/categories?post=598"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/tags?post=598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}