Recent Changes for "Concurrency" - spark-schemehttp://spark-scheme.wikispot.org/ConcurrencyRecent Changes of the page "Concurrency" on spark-scheme.en-us Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-08-10 17:09:24vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 284: </td> <td> Line 284: </td> </tr> <tr> <td> <span>-</span> ;; Modify global state here.<br> <span>-</span> ) </td> <td> <span>+ (begin<br> + </span> ;; Modify global state here.<br> <span>+ </span> )<span>)</span> </td> </tr> <tr> <td> Line 297: </td> <td> Line 298: </td> </tr> <tr> <td> <span>-</span> ;; Modify global state here.<br> <span>-</span> ) </td> <td> <span>+ (begin<br> + </span> ;; Modify global state here.<br> <span>+ </span> )<span>)</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-08-10 17:08:49vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 282: </td> <td> Line 282: </td> </tr> <tr> <td> <span>- ;; Global state is BAD!!<br> - &gt; (define global-state 0)</span> </td> <td> </td> </tr> <tr> <td> Line 286: </td> <td> Line 284: </td> </tr> <tr> <td> <span>- (set! global-state (add1 global-state))))<br> - &gt; (async modify-global-state)<br> - &gt; (async modify-global-state)<br> - &gt; global-state<br> - 2</span> </td> <td> <span>+ ;; Modify global state here.<br> + )</span> </td> </tr> <tr> <td> Line 300: </td> <td> Line 295: </td> </tr> <tr> <td> <span>- (define (counter-with-named-atomic)<br> - (atomic "counter"<br> - (begin<br> - (set! count (add1 count))<br> - (printf "~a " count))))<br> - <br> - }}}</span> </td> <td> <span>+ &gt; (define (modify-global-state)<br> + (atomic "lock-name"<br> + ;; Modify global state here.<br> + )<br> + <br> + }}}<br> + <br> + All constant-time procedures and operations are thread-safe because they are atomic. For example, ''set!'' assigns to a variable as an atomic action with respect to all threads, so that no thread can see a "half-assigned" variable. Similarly, ''vector-set!'' assigns to a vector atomically. The ''hash-table-put!'' procedure is not atomic, but the table is protected by a lock. Port operations are generally not atomic, but they are thread-safe in the sense that a byte consumed by one thread from an input port will not be returned also to another thread, and procedures like ''port-commit-peeked'' and ''write-bytes-avail'' offer specific concurrency guarantees. See ["MzScheme Library Reference"] for more information.</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-08-10 17:03:34vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 278: </td> <td> Line 278: </td> </tr> <tr> <td> <span>-</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously.<span>&nbsp;Note that the following samples are rather contrived, as ''set!'' is already atomic.</span> </td> <td> <span>+</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-08-10 17:01:40vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 278: </td> <td> Line 278: </td> </tr> <tr> <td> <span>-</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously. </td> <td> <span>+</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously.<span>&nbsp;Note that the following samples are rather contrived, as ''set!'' is already atomic.</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-08-09 17:26:16vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 302: </td> <td> Line 302: </td> </tr> <tr> <td> <span>-</span> (set! count (add1 count))<br> <span>-</span> (printf "~a " count)))<br> <span>-</span> <br> <span>-</span> }}} </td> <td> <span>+ (begin<br> + </span> (set! count (add1 count))<br> <span>+ </span> (printf "~a " count)))<span>)</span><br> <span>+</span> <br> <span>+</span> }}} </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:17:46vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 296: </td> <td> Line 296: </td> </tr> <tr> <td> <span>-</span> Usually ''atomic'' makes use of a single, global synchronization object. New, special purpose synchronization objects can be created using ''named atomics''. Code blocks can choose which synchronization object to use by specifying it<span>'</span>s name. </td> <td> <span>+</span> Usually ''atomic'' makes use of a single, global synchronization object. New, special purpose synchronization objects can be created using ''named atomics''. Code blocks can choose which synchronization object to use by specifying its name. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:17:35vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 264: </td> <td> Line 264: </td> </tr> <tr> <td> <span>-</span> If you have programmed in languages like Java or Python, you might have used ''threads'' to simulate concurrency. Spark too have threads. But unlike the aforementioned languages, Spark's multi-threading capabilities are not dependent on the host operating system. Threads is part of the Spark runtime itself. A new thread is created with a call to the ''thread'' procedure. It takes a<span>nother procedure as it'</span>s argument, which will be execute in the new thread. The return value is a thread descriptor object. </td> <td> <span>+</span> If you have programmed in languages like Java or Python, you might have used ''threads'' to simulate concurrency. Spark too have threads. But unlike the aforementioned languages, Spark's multi-threading capabilities are not dependent on the host operating system. Threads is part of the Spark runtime itself. A new thread is created with a call to the ''thread'' procedure. It takes a<span>&nbsp;procedure a</span>s argument, which will be execute in the new thread. The return value is a thread descriptor object. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:17:10vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 244: </td> <td> Line 244: </td> </tr> <tr> <td> <span>-</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any argument. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''callback-proc'' will receive as <span>it's </span>argument the value that ''proc'' evaluates to. ''callback-proc'' can be null. </td> <td> <span>+</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any argument. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''callback-proc'' will receive as argument the value that ''proc'' evaluates to. ''callback-proc'' can be null. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:16:55vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 215: </td> <td> Line 215: </td> </tr> <tr> <td> <span>-</span> Now clients can send messages to "trig-server" by appending the machine name or IP to it<span>'</span>s identifier. Here is a sample client that can interact with the remote trig-server: </td> <td> <span>+</span> Now clients can send messages to "trig-server" by appending the machine name or IP to its identifier. Here is a sample client that can interact with the remote trig-server: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:16:46vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 171: </td> <td> Line 171: </td> </tr> <tr> <td> <span>-</span> The process represented by ''test-server'' can be brought under watch by passing it<span>'</span>s proc-id to ''watch-server''. When it dies, it is restarted by the watcher. This is demonstrated in the following session: </td> <td> <span>+</span> The process represented by ''test-server'' can be brought under watch by passing its proc-id to ''watch-server''. When it dies, it is restarted by the watcher. This is demonstrated in the following session: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:16:35vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 89: </td> <td> Line 89: </td> </tr> <tr> <td> <span>-</span> Let us extend the trig-server with a complete implementation of inter-process communication. The client process should include it<span>'</span>s process id as the first element of the message. ''trig-server'' will compute the result and send it back to the client. </td> <td> <span>+</span> Let us extend the trig-server with a complete implementation of inter-process communication. The client process should include its process id as the first element of the message. ''trig-server'' will compute the result and send it back to the client. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:16:23vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 72: </td> <td> Line 72: </td> </tr> <tr> <td> <span>-</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in it<span>'</span>s own parallel world, we can go on with other business as it does the computations. </td> <td> <span>+</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in its own parallel world, we can go on with other business as it does the computations. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-22 14:16:16vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 63: </td> <td> Line 63: </td> </tr> <tr> <td> <span>-</span> To use the ''trig server'', load ''trig-server.ss'' into Spark and spawn a process with the procedure ''trig-server'' as it<span>'</span>s callback. </td> <td> <span>+</span> To use the ''trig server'', load ''trig-server.ss'' into Spark and spawn a process with the procedure ''trig-server'' as its callback. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:22:10vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 295: </td> <td> Line 295: </td> </tr> <tr> <td> </td> <td> <span>+ <br> + Usually ''atomic'' makes use of a single, global synchronization object. New, special purpose synchronization objects can be created using ''named atomics''. Code blocks can choose which synchronization object to use by specifying it's name.<br> + <br> + {{{<br> + <br> + (define (counter-with-named-atomic)<br> + (atomic "counter"<br> + (set! count (add1 count))<br> + (printf "~a " count)))<br> + <br> + }}}</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:17:28vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 278: </td> <td> Line 278: </td> </tr> <tr> <td> <span>-</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. <span>''(see the section on Concurrency)''. </span>Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously. </td> <td> <span>+</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes simultaneously. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:16:30vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 264: </td> <td> Line 264: </td> </tr> <tr> <td> <span>-</span> If you have programmed in languages like Java or Python, you might have used ''threads'' to simulate concurrency. Spark too have threads. But unlike the aforementioned languages, Spark's multi-threading capabilities are not dependent on the host operating system. Threads is part of the Spark runtime itself. A new thread is created with a call to the ''thread'' procedure. It takes a procedure as it's argument, which will be execute in the new thread. The return value is a thread descriptor object. </td> <td> <span>+</span> If you have programmed in languages like Java or Python, you might have used ''threads'' to simulate concurrency. Spark too have threads. But unlike the aforementioned languages, Spark's multi-threading capabilities are not dependent on the host operating system. Threads is part of the Spark runtime itself. A new thread is created with a call to the ''thread'' procedure. It takes a<span>nother</span> procedure as it's argument, which will be execute in the new thread. The return value is a thread descriptor object. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:15:51vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 244: </td> <td> Line 244: </td> </tr> <tr> <td> <span>-</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any argument<span>s</span>. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''callback-proc'' will receive as it's argument the value that ''proc'' evaluates to. ''callback-proc'' can be null. </td> <td> <span>+</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any argument. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''callback-proc'' will receive as it's argument the value that ''proc'' evaluates to. ''callback-proc'' can be null. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:15:04vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 242: </td> <td> Line 242: </td> </tr> <tr> <td> <span>-</span> A<span>n a</span>synchronous procedures can be used to get a time consuming computation done in the background. It is another way of creating processes without the messaging infrastructure. The computation is defined as a procedure <span>and in</span>v<span>oke it with a c</span>al<span>l to</span> ''async''. </td> <td> <span>+</span> Asynchronous procedures can be used to get a time consuming computation done in the background. It is another way of creating processes<span>,</span> without the messaging infrastructure. The computation is defined as a procedure <span>which is e</span>val<span>uated using</span> ''async''. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:14:07vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 237: </td> <td> Line 237: </td> </tr> <tr> <td> <span>-</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service on port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port. Thus components in a Spark program can be distributed across a network with very little additional programming effort. <span>This is an important feature for a language that lives in the age of "cloud computing". </span>One other language that offer this convenience is [http://erlang.org/ Erlang], which inspired and influenced the design of Spark concurrent objects. </td> <td> <span>+</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service on port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port. Thus components in a Spark program can be distributed across a network with very little additional programming effort. One other language that offer this convenience is [http://erlang.org/ Erlang], which inspired and influenced the design of Spark concurrent objects. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:13:05vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 215: </td> <td> Line 215: </td> </tr> <tr> <td> <span>-</span> Now clients can send messages to "trig-server" by appending the machine name or IP to it. Here is a sample client that can interact with the remote trig-server: </td> <td> <span>+</span> Now clients can send messages to "trig-server" by appending the machine name or IP to it<span>'s identifier</span>. Here is a sample client that can interact with the remote trig-server: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:12:27vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 203: </td> <td> Line 203: </td> </tr> <tr> <td> <span>-</span> In distributed computing a program is split<span>&nbsp;up</span> into parts that run simultaneously on multiple computers communicating over a network. Spark processes can be made to send and receive messages over the network. This does not require any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''receive'' procedure to get the request. <span>We need to use</span> a new procedure, though. This is called ''remoting!'' and it starts an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> <td> <span>+</span> In distributed computing a program is split into parts that run simultaneously on multiple computers communicating over a network. Spark processes can be made to send and receive messages over the network. This does not require any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''receive'' procedure to get the request. <span>To actually send and receive messages over the network, we need</span> a new procedure, though. This is called ''remoting!'' and it starts an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All <span>of </span>that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:10:36vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 201: </td> <td> Line 201: </td> </tr> <tr> <td> <span>-</span> ==== <span>Processes and d</span>istributed computing ==== </td> <td> <span>+</span> ==== <span>D</span>istributed computing ==== </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:10:22vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 190: </td> <td> Line 190: </td> </tr> <tr> <td> </td> <td> <span>+ </span> </td> </tr> <tr> <td> Line 191: </td> <td> Line 192: </td> </tr> <tr> <td> </td> <td> <span>+ </span> </td> </tr> <tr> <td> Line 192: </td> <td> Line 194: </td> </tr> <tr> <td> </td> <td> <span>+ </span> </td> </tr> <tr> <td> Line 193: </td> <td> Line 196: </td> </tr> <tr> <td> <span>-</span> '''(descriptor proc-id)''': Returns the thread descriptor object that the process internally<span>&nbsp;uses</span>.<br> <span>-</span> '''(message-channel proc-id)''': Returns the asynchronous message channel object that the process internally<span>&nbsp;uses</span>. </td> <td> <span>+ <br> +</span> '''(descriptor proc-id)''': Returns the thread descriptor object that the process <span>uses </span>internally.<br> <span>+ <br> +</span> '''(message-channel proc-id)''': Returns the asynchronous message channel object that the process <span>uses </span>internally. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:09:18vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 148: </td> <td> Line 148: </td> </tr> <tr> <td> <span>-</span> A system is ''fault tolerant'' if it can detect errors and repair itself. Spark process <span>can have</span> fault tolerance with the help of ''watcher'' processes. A ''watcher'' process is notified by the system when a ''watched'' process die<span>s</span> or exit<span>s</span>. The following code snippet introduces the procedure ''watch'' that enables a process to keep an eye on another process: </td> <td> <span>+</span> A system is ''fault tolerant'' if it can detect errors and repair itself. <span>A </span>Spark process <span>implements</span> fault tolerance with the help of ''watcher'' processes. A ''watcher'' process is notified by the system when a ''watched'' process die or exit. The following code snippet introduces the procedure ''watch'' that enables a process to keep an eye on another process: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:08:35vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 146: </td> <td> Line 146: </td> </tr> <tr> <td> <span>-</span> ==== <span>Processes and f</span>ault tolerance ==== </td> <td> <span>+</span> ==== <span>F</span>ault tolerance ==== </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:08:22vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 144: </td> <td> Line 144: </td> </tr> <tr> <td> <span>- With c</span>oncurrent objects <span>we ha</span>ve a powerful tool to model the <span>real world</span>. Like objects in the real world, Spark processes live and execute independently. They interact with each other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously unknown intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming]. </td> <td> <span>+ C</span>oncurrent objects <span>gi</span>ve<span>s us</span> a powerful tool to model the <span>world around us</span>. Like objects in the real world, Spark processes live and execute independently. They interact with each other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously unknown intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming]. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:07:31vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 128: </td> <td> Line 128: </td> </tr> <tr> <td> <span>-</span> To try our <span>cha</span>n<span>g</span>e<span>d</span> code, <span>you</span> need to load both trig-server.ss and trig-client.ss: </td> <td> <span>+</span> To try our ne<span>w</span> code, <span>we</span> need to load both trig-server.ss and trig-client.ss: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:07:13vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 115: </td> <td> Line 115: </td> </tr> <tr> <td> <span>-</span> Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and the value to apply the trig function. Internally we spawn a new process that will send the request to the server, get the response and print it. </td> <td> <span>+</span> Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and the value to apply the trig function<span>&nbsp;to</span>. Internally we spawn a new process that will send the request to the server, get the response and print it. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:06:32vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 89: </td> <td> Line 89: </td> </tr> <tr> <td> <span>-</span> Let us extend the trig-server with a complete implementation of inter-process communication. The <span>sending</span> process should include it's process id as the first element of the message. ''trig-server'' will compute the result and send it back to th<span>at process</span>. </td> <td> <span>+</span> Let us extend the trig-server with a complete implementation of inter-process communication. The <span>client</span> process should include it's process id as the first element of the message. ''trig-server'' will compute the result and send it back to th<span>e client</span>. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:05:27vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 72: </td> <td> Line 72: </td> </tr> <tr> <td> <span>-</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with other business<span>es</span> as it does the computations. </td> <td> <span>+</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with other business as it does the computations. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:04:57vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 35: </td> <td> Line 35: </td> </tr> <tr> <td> <span>-</span> Let us <span>tr</span>y <span>to get a better understanding of</span> concurrent objects <span>with the help of a simple exampl</span>e. Here we define an object that can act as a background service for doing trigonometric calculations. It waits for messages in a loop. A message is packed as a list <span>data structure</span> with the first element identifying the trigonometric function and the rest of the elements being <span>it</span>'s arguments. When a message arrives, it is unpacked using the ''match'' procedure and an appropriate trigonometric function is executed and the result is displayed. If it receives the special message 'exit, the concurrent object kills itself. </td> <td> <span>+</span> Let us <span>stud</span>y <span>a small program where</span> concurrent objects <span>are put to good us</span>e. Here we define an object that can act as a background service for doing trigonometric calculations. It waits for messages in a loop. A message is packed as a list with the first element identifying the trigonometric function and the rest of the elements being <span>that function</span>'s arguments. When a message arrives, it is unpacked using the ''match'' procedure and an appropriate trigonometric function is executed and the result is displayed. If it receives the special message 'exit, the concurrent object kills itself. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:03:33vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 16: </td> <td> Line 16: </td> </tr> <tr> <td> <span>-</span> '''(spawn proc)''': Creates a new process<span>&nbsp;that evaluates the procedure ''proc''</span>. The <span>return value is an integer that identifies the</span> process. It can take ''n'' number of optional arguments which can be used to initialize the state of the new process.<br> <span>-</span> '''(send pid)''': <span>Sends a message to the process identified by ''pid''. Message sending is asynchronous</span>.<br> <span>-</span> '''(receive pid)''': Receives a message from the message queue of the process identified by ''pid''. Calls to ''receive'' usually make use of the pattern matching facility provided by the ''match'' library. ''receive'' usually follows coding pattern given below: </td> <td> <span>+</span> '''(spawn proc)''': Creates a new process. The <span>procedure represented by ''proc'' is evaluated in that process. The return value of ''spawn'' is an integer that identifies the new</span> process. It can take ''n'' number of optional arguments which can be used to initialize the state of the new process.<br> <span>+ <br> +</span> '''(send pid)''': <span>Asynchronously sends a message to the process identified by ''pid''</span>.<br> <span>+ <br> +</span> '''(receive pid)''': Receives a message from the message queue of the process identified by ''pid''. Calls to ''receive'' usually make use of the pattern matching facility provided by the ''match'' library. ''receive'' usually follows <span>the </span>coding pattern given below: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-07-16 15:01:30vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 9: </td> <td> Line 9: </td> </tr> <tr> <td> <span>- Spark allows several computations to execute simultaneously, possibly interacting with each other. In programming parlance this is known as multi-processing, multi-threading, concurrency etc. Programming languages usually depend on the host operating systems capabilities to implement concurrency. Spark has built-in concurrency. It provide multi-threading without any help from the underlying operating system. This has some important consequences:</span> </td> <td> <span>+ Spark allows several computations to execute simultaneously, possibly interacting with each other. In programming parlance this is known as multi-processing, multi-threading, concurrency etc. Programming languages usually depend on the host operating system's capabilities to implement concurrency. Spark has built-in concurrency. It provide multi-threading without any help from the underlying operating system. This has some important consequences:</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-21 12:49:27vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 267: </td> <td> Line 267: </td> </tr> <tr> <td> <span>-</span> See the <span>[</span>MzScheme library reference http://spark-scheme.wikispot.org/MzScheme_Library_Reference] for more information on threads. </td> <td> <span>+</span> See the MzScheme library reference <span>[</span>http://spark-scheme.wikispot.org/MzScheme_Library_Reference] for more information on threads. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-21 12:49:10vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 267: </td> <td> Line 267: </td> </tr> <tr> <td> <span>-</span> See the [MzScheme library reference <span>"</span>http://spark-scheme.wikispot.org/MzScheme_Library_Reference<span>"</span>] for more information on threads. </td> <td> <span>+</span> See the [MzScheme library reference http://spark-scheme.wikispot.org/MzScheme_Library_Reference] for more information on threads. </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-21 12:48:49vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 10: </td> <td> Line 10: </td> </tr> <tr> <td> </td> <td> <span>+ </span> </td> </tr> <tr> <td> Line 15: </td> <td> Line 16: </td> </tr> <tr> <td> <span>-</span> '''(spawn proc)''': Creates a new process that evaluates the procedure ''proc''. The return value is an integer that identifies the process. It take<span>s an</span> optional arguments which can be used to initialize the state of the new process. </td> <td> <span>+</span> '''(spawn proc)''': Creates a new process that evaluates the procedure ''proc''. The return value is an integer that identifies the process. It <span>can </span>take<span>&nbsp;&nbsp;''n'' number of</span> optional arguments which can be used to initialize the state of the new process. </td> </tr> <tr> <td> Line 17: </td> <td> Line 18: </td> </tr> <tr> <td> <span>-</span> '''(receive pid)''': Receives a message from the message queue of the process identified by ''pid''. Calls to ''receive'' usually make use of the pattern matching facility provided by the ''match'' library<span>&nbsp;and has the</span> follow<span>ing coding pattern</span>: </td> <td> <span>+</span> '''(receive pid)''': Receives a message from the message queue of the process identified by ''pid''. Calls to ''receive'' usually make use of the pattern matching facility provided by the ''match'' library<span>. ''receive'' usually</span> follow<span>s coding pattern given below</span>: </td> </tr> <tr> <td> Line 32: </td> <td> Line 33: </td> </tr> <tr> <td> <span>-</span> Let us try to get a better understanding of concurrent objects with the help of a simple example. Here we define an object that can act as background service for doing trigonometric calculations. It waits for messages in a loop. A message is packed as a list data structure with the first element identifying the trigonometric function<span>&nbsp;to execute</span> and the rest of the elements being it's arguments. When a message arrives, it is unpacked using the ''match'' procedure and an appropriate trigonometric function is executed and the result is displayed. If it receives the special message 'exit, the concurrent object kills itself. </td> <td> <span>+</span> Let us try to get a better understanding of concurrent objects with the help of a simple example. Here we define an object that can act as <span>a </span>background service for doing trigonometric calculations. It waits for messages in a loop. A message is packed as a list data structure with the first element identifying the trigonometric function and the rest of the elements being it's arguments. When a message arrives, it is unpacked using the ''match'' procedure and an appropriate trigonometric function is executed and the result is displayed. If it receives the special message 'exit, the concurrent object kills itself. </td> </tr> <tr> <td> Line 69: </td> <td> Line 70: </td> </tr> <tr> <td> <span>-</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with o<span>u</span>r business as it does the computations. </td> <td> <span>+</span> Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with o<span>the</span>r busines<span>se</span>s as it does the computations. </td> </tr> <tr> <td> Line 112: </td> <td> Line 113: </td> </tr> <tr> <td> <span>-</span> Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and <span>it's ar</span>g<span>ument as it's parameters</span>. Internally we spawn a new process that will send the request to the server get the response and print it. </td> <td> <span>+</span> Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and <span>the value to apply the tri</span>g<span>&nbsp;function</span>. Internally we spawn a new process that will send the request to the server<span>,</span> get the response and print it. </td> </tr> <tr> <td> Line 125: </td> <td> Line 126: </td> </tr> <tr> <td> <span>-</span> To try our changed code, you need to load both trig-server.ss and trig-client.ss<span>&nbsp;to the Spark environment.</span> </td> <td> <span>+</span> To try our changed code, you need to load both trig-server.ss and trig-client.ss<span>:</span> </td> </tr> <tr> <td> Line 141: </td> <td> Line 142: </td> </tr> <tr> <td> <span>- With concurrent objects we have a powerful tool to model the real world in software. Like objects in the real world, Spark processes live and execute independently. They interact with other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming].</span> </td> <td> <span>+ With concurrent objects we have a powerful tool to model the real world. Like objects in the real world, Spark processes live and execute independently. They interact with each other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously unknown intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming].</span> </td> </tr> <tr> <td> Line 184: </td> <td> Line 185: </td> </tr> <tr> <td> <span>- '''Exercise 1: ''' Modify the procedure ''watch-server'' so that the same watcher process is re-used to watch all new ''test-server'' processes.<br> - </span> </td> <td> </td> </tr> <tr> <td> Line 191: </td> <td> Line 190: </td> </tr> <tr> <td> <span>-</span> '''(unregister proc-id name)''': Removes the ''proc-id''<span>&nbsp;to </span>''name'' mapping<span>&nbsp;from the system</span>. </td> <td> <span>+</span> '''(unregister proc-id name)''': Removes the ''proc-id''<span>-</span>''name'' mapping. </td> </tr> <tr> <td> Line 197: </td> <td> Line 196: </td> </tr> <tr> <td> <span>-</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and receive messages over the network. This does not <span>need</span> any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''receive'' procedure to <span>know what the client is</span> request<span>ing</span>. We need to use a new procedure, though. This is called ''remoting!'' and it starts<span>&nbsp;the</span> an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> <td> <span>+</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process<span>es</span> can be made to send and receive messages over the network. This does not <span>require</span> any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''receive'' procedure to <span>get the</span> request. We need to use a new procedure, though. This is called ''remoting!'' and it starts an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> </tr> <tr> <td> Line 209: </td> <td> Line 208: </td> </tr> <tr> <td> <span>-</span> Now<span>&nbsp;any</span> client can send messages to<span>&nbsp;the process</span> "trig-server" by appending the machine name or IP to it. Here is a sample client that can interact with the remote trig-server: </td> <td> <span>+</span> Now client<span>s</span> can send messages to "trig-server" by appending the machine name or IP to it. Here is a sample client that can interact with the remote trig-server: </td> </tr> <tr> <td> Line 231: </td> <td> Line 230: </td> </tr> <tr> <td> <span>-</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service o<span>f</span> port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port. Thus components in a Spark program can be distributed across a network with little additional programming effort. This is an important feature for a language that lives in th<span>is</span> age of "cloud computing". One other language that offer this convenience is [http://erlang.org/ Erlang], which inspired and influenced the design of Spark concurrent objects.<span><br> - </span> </td> <td> <span>+</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service o<span>n</span> port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port. Thus components in a Spark program can be distributed across a network with <span>very </span>little additional programming effort. This is an important feature for a language that lives in th<span>e</span> age of "cloud computing". One other language that offer this convenience is [http://erlang.org/ Erlang], which inspired and influenced the design of Spark concurrent objects. </td> </tr> <tr> <td> Line 237: </td> <td> Line 235: </td> </tr> <tr> <td> <span>-</span> An asynchronous procedures can be used to get a time consuming computation done in the background. It is another way of creating processes without the messaging infrastructure. <span>You</span> define<span>&nbsp;the computation</span> as a procedure and invoke it with a call to ''async''.<br> <span>-</span> <br> <span>-</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any arguments. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''call<span>ed</span>-proc'' will receive as it's argument the value that ''proc'' evaluates to. ''call<span>ed</span>-proc'' can be null. </td> <td> <span>+</span> An asynchronous procedures can be used to get a time consuming computation done in the background. It is another way of creating processes without the messaging infrastructure. <span>The computation is</span> define<span>d</span> as a procedure and invoke it with a call to ''async''.<br> <span>+</span> <br> <span>+</span> '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any arguments. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''call<span>back</span>-proc'' will receive as it's argument the value that ''proc'' evaluates to. ''call<span>back</span>-proc'' can be null. </td> </tr> <tr> <td> Line 269: </td> <td> Line 267: </td> </tr> <tr> <td> <span>-</span> See the MzScheme <span>do</span>c<span>u</span>men<span>tation</span> for more information on threads. </td> <td> <span>+</span> See the <span>[</span>MzScheme <span>library referen</span>c<span>e "http://spark-sche</span>me<span>.wikispot.org/MzScheme_Library_Refere</span>n<span>ce"]</span> for more information on threads. </td> </tr> <tr> <td> Line 273: </td> <td> Line 271: </td> </tr> <tr> <td> <span>-</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. ''(see the section on Concurrency)''. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes <span>at the same time.</span> </td> <td> <span>+</span> The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. ''(see the section on Concurrency)''. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes <span>simultaneously.</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-21 12:30:55vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 6: </td> <td> Line 6: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-20 20:58:02vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 1: </td> <td> Line 1: </td> </tr> <tr> <td> <span>-</span> next: ["Networking"] previous: ["<span>Co</span>n<span>c</span>u<span>rrency</span>"] top: ["Programming spark" Contents] </td> <td> <span>+</span> next: ["Networking"] previous: ["<span>I</span>n<span>p</span>u<span>t/Output</span>"] top: ["Programming spark" Contents] </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-06-20 20:56:56vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 1: </td> <td> Line 1: </td> </tr> <tr> <td> <span>- </span> </td> <td> <span>+ next: ["Networking"] previous: ["Concurrency"] top: ["Programming spark" Contents]</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-10 12:26:44vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 1: </td> <td> Line 1: </td> </tr> <tr> <td> <span>- = Concurrency =</span> </td> <td> <span>+ </span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-03 13:29:54vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 1: </td> <td> Line 1: </td> </tr> <tr> <td> <span>-</span> <span>=</span>= Concurrency =<span>=</span> </td> <td> <span>+</span> = Concurrency = </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 13:38:27vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 198: </td> <td> Line 198: </td> </tr> <tr> <td> <span>-</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and recive messages over the network. This does not need any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''recive'' procedure to know what the client is requesting. We need to use a new procedure, though. This is called ''remoting!'' and it starts the an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> <td> <span>+</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and rec<span>e</span>ive messages over the network. This does not need any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''rec<span>e</span>ive'' procedure to know what the client is requesting. We need to use a new procedure, though. This is called ''remoting!'' and it starts the an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process: </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 13:32:37vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 232: </td> <td> Line 232: </td> </tr> <tr> <td> <span>-</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service of port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port. </td> <td> <span>+</span> Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service of port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port.<span>&nbsp;Thus components in a Spark program can be distributed across a network with little additional programming effort. This is an important feature for a language that lives in this age of "cloud computing". One other language that offer this convenience is [http://erlang.org/ Erlang], which inspired and influenced the design of Spark concurrent objects.</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 13:27:04vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 198: </td> <td> Line 198: </td> </tr> <tr> <td> <span>-</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and recive messages over the network. This does not need any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''recive'' procedure to know what the client is requesting. We need to use a new procedure, though. This is called ''remoting!'' and it starts the an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls. </td> <td> <span>+</span> In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and recive messages over the network. This does not need any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''recive'' procedure to know what the client is requesting. We need to use a new procedure, though. This is called ''remoting!'' and it starts the an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls.<span>&nbsp;The ''trig-server'' we have written can serve clients in a networked environment, without any modification. Let us see how to start it as a server process:<br> + <br> + {{{<br> + <br> + &gt; (load "trig-server.ss")<br> + &gt; (remoting!)<br> + #&lt;thread&gt;<br> + &gt; (define pid (spawn trig-server))<br> + &gt; (register pid "trig-server")<br> + <br> + }}}<br> + <br> + Now any client can send messages to the process "trig-server" by appending the machine name or IP to it. Here is a sample client that can interact with the remote trig-server:<br> + <br> + {{{<br> + <br> + &gt; (define (trig-client pid)<br> + (let loop ((msg (receive pid)))<br> + (printf "~a~n" msg)<br> + (flush-output)<br> + (loop (receive pid))))<br> + &gt; (remoting! 1445)<br> + #&lt;thread&gt;<br> + &gt; (define pid (spawn trig-client))<br> + &gt; (register pid "trig-client")<br> + &gt; (send "trig-server@localhost" (list "trig-client@localhost:1445" 'sin 3.4))<br> + #t<br> + -0.2555411020268312<br> + &gt; (send "trig-server@localhost" (list "trig-client@localhost:1445" 'cos 1.2))<br> + #t<br> + 0.3623577544766736<br> + <br> + }}}<br> + <br> + Note the way we specify the remote process id appended with the machine name. We need to start the ''remoting'' service so as to get back the responses send by ''trig-server''. We start the client side remoting service of port 1445, because the default port 1383 is already bound by ''trig-server''. If the server and client processes are actually running on two machines, we need not change the port.</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 13:03:20vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 198: </td> <td> Line 198: </td> </tr> <tr> <td> </td> <td> <span>+ In distributed computing a program is split up into parts that run simultaneously on multiple computers communicating over a network. Spark process can be made to send and recive messages over the network. This does not need any extensive modification of existing code. A client process can send messages to a server process running on another machine using the ''send'' procedure itself. The server process on the other end of the network can use the same old ''recive'' procedure to know what the client is requesting. We need to use a new procedure, though. This is called ''remoting!'' and it starts the an internal TCP server that acts as a mediator between the distributed processes. The programmer need not worry about how the messages are packed, delivered and unpacked over the wire. All that is taken care of by the ''send'', ''receive'' and ''remoting!'' procedure calls.<br> + </span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 12:56:45vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 196: </td> <td> Line 196: </td> </tr> <tr> <td> </td> <td> <span>+ ==== Processes and distributed computing ====<br> + <br> + </span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 12:55:09vijaymathew(quick edit) <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 144: </td> <td> Line 144: </td> </tr> <tr> <td> <span>-</span> ==== Processes and fault toleran<span>t</span> ==== </td> <td> <span>+</span> ==== Processes and fault toleran<span>ce</span> ==== </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-02 12:39:18vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 3: </td> <td> Line 3: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 6: </td> <td> Line 4: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 8: </td> <td> Line 5: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 11: </td> <td> Line 7: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 14: </td> <td> Line 8: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 17: </td> <td> Line 10: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 20: </td> <td> Line 11: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 24: </td> <td> Line 12: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 27: </td> <td> Line 14: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 31: </td> <td> Line 16: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 34: </td> <td> Line 17: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 38: </td> <td> Line 18: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 43: </td> <td> Line 20: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ {{{</span> </td> </tr> <tr> <td> Line 50: </td> <td> Line 23: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 54: </td> <td> Line 24: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 56: </td> <td> Line 25: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 58: </td> <td> Line 26: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 60: </td> <td> Line 27: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 62: </td> <td> Line 28: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 64: </td> <td> Line 29: </td> </tr> <tr> <td> <span>- <br> -</span> (<span>(</span>_<span>)</span> handle-unexpected-message))))<br> <span>-</span> <br> <span>- <br> - <br> -</span> }}}<span><br> - <br> - </span> </td> <td> <span>+</span> (_ handle-unexpected-message))))<br> <span>+</span> <br> <span>+</span> }}} </td> </tr> <tr> <td> Line 75: </td> <td> Line 35: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ {{{</span> </td> </tr> <tr> <td> Line 83: </td> <td> Line 39: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 87: </td> <td> Line 41: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 90: </td> <td> Line 42: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 92: </td> <td> Line 43: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 94: </td> <td> Line 44: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 96: </td> <td> Line 45: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 98: </td> <td> Line 46: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 100: </td> <td> Line 47: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 102: </td> <td> Line 48: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 104: </td> <td> Line 49: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 106: </td> <td> Line 50: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 108: </td> <td> Line 51: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 110: </td> <td> Line 52: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 112: </td> <td> Line 53: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 114: </td> <td> Line 54: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 116: </td> <td> Line 55: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 118: </td> <td> Line 56: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 120: </td> <td> Line 57: </td> </tr> <tr> <td> <span>- </span> </td> <td> <span>+ (newline)))))<br> + <br> + }}}<br> + <br> + To use the ''trig server'', load ''trig-server.ss'' into Spark and spawn a process with the procedure ''trig-server'' as it's callback.<br> + <br> + {{{<br> + <br> + &gt; (load "trig-server.ss")<br> + &gt; (define pid (spawn trig-server))<br> + <br> + }}}<br> + <br> + Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with our business as it does the computations.<br> + <br> + {{{<br> + <br> + &gt; (send pid (list 'sin 3.4))<br> + sin of 3.4 is -0.2555411020268312<br> + &gt; (send pid (list 'cos 2.1))<br> + cos of 2.1 is -0.5048461045998575<br> + &gt; (send pid (list 'tan 3.5))<br> + tan of 3.5 is 0.3745856401585947<br> + &gt; (send pid (list 'blah 7))<br> + Don't know the trif function (blah 7)<br> + &gt; (send pid 'exit)<br> + Goodbye.<br> + <br> + }}}<br> + <br> + Let us extend the trig-server with a complete implementation of inter-process communication. The sending process should include it's process id as the first element of the message. ''trig-server'' will compute the result and send it back to that process.<br> + <br> + {{{<br> + <br> + (import (match))<br> + <br> + (define (trig-server pid)<br> + (let loop ((message (receive pid)))<br> + (cond<br> + ((not (eq? message 'exit))<br> + (match message<br> + ((sender-pid 'sin a)<br> + (send sender-pid (sin a)))<br> + ((sender-pid 'cos a)<br> + (send sender-pid (cos a)))<br> + ((sender-pid 'tan a)<br> + (send sender-pid (tan a)))<br> + (_<br> + (printf "Don't know the trig function ~a~n" message)))<br> + (loop (receive pid)))<br> + (else<br> + (display "Goodbye.")</span> </td> </tr> <tr> <td> Line 125: </td> <td> Line 113: </td> </tr> <tr> <td> <span>- <br> - <br> - To use the ''trig server'', load ''trig-server.ss'' into Spark and spawn a process with the procedure ''trig-server'' as it's callback.<br> - <br> - <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and it's argument as it's parameters. Internally we spawn a new process that will send the request to the server get the response and print it.<br> + <br> + {{{<br> + <br> + (define (trig-client server-pid func val)<br> + (spawn<br> + (lambda (pid)<br> + (send server-pid (list pid func val))<br> + (printf "(~a ~a) = ~a" func val (receive pid))<br> + (flush-output))))<br> + <br> + }}}<br> + <br> + To try our changed code, you need to load both trig-server.ss and trig-client.ss to the Spark environment.<br> + <br> + {{{</span> </td> </tr> <tr> <td> Line 136: </td> <td> Line 131: </td> </tr> <tr> <td> <span>- <br> - &gt; (define pid (spawn trig-server))<br> - <br> - <br> - <br> - }}}<br> - <br> - <br> - <br> - Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with our business as it does the computations.<br> - <br> - <br> - <br> - {{{<br> - <br> - <br> - <br> - &gt; (send pid (list 'sin 3.4))<br> - <br> - sin of 3.4 is -0.2555411020268312<br> - <br> - &gt; (send pid (list 'cos 2.1))<br> - <br> - cos of 2.1 is -0.5048461045998575<br> - <br> - &gt; (send pid (list 'tan 3.5))<br> - <br> - tan of 3.5 is 0.3745856401585947<br> - <br> - &gt; (send pid (list 'blah 7))<br> - <br> - Don't know the trif function (blah 7)<br> - <br> - &gt; (send pid 'exit)<br> - <br> - Goodbye.<br> - <br> - <br> - <br> - }}}<br> - <br> - <br> - <br> - Let us extend the trig-server with a complete implementation of inter-process communication. The sending process should include it's process id as the first element of the message. ''trig-server'' will compute the result and send it back to that process.<br> - <br> - <br> - <br> - {{{<br> - <br> - <br> - <br> - (import (match))<br> - <br> - <br> - <br> - (define (trig-server pid)<br> - <br> - (let loop ((message (receive pid)))<br> - <br> - (cond<br> - <br> - ((not (eq? message 'exit))<br> - <br> - (match message<br> - <br> - ((sender-pid 'sin a)<br> - <br> - (send sender-pid (sin a)))<br> - <br> - ((sender-pid 'cos a)<br> - <br> - (send sender-pid (cos a)))<br> - <br> - ((sender-pid 'tan a)<br> - <br> - (send sender-pid (tan a)))<br> - <br> - (_<br> - <br> - (printf "Don't know the trig function ~a~n" message)))<br> - <br> - (loop (receive pid)))<br> - <br> - (else<br> - <br> - (display "Goodbye.")<br> - <br> - (newline)))))<br> - <br> - <br> - <br> - }}}<br> - <br> - <br> - <br> - Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and it's argument as it's parameters. Internally we spawn a new process that will send the request to the server get the response and print it.<br> - <br> - <br> - <br> - {{{<br> - <br> - <br> - <br> - (define (trig-client server-pid func val)<br> - </span> </td> <td> <span>+ &gt; (load "trig-client.ss")<br> + &gt; (define server-pid (spawn trig-server))<br> + &gt; (trig-client server-pid 'sin 10)<br> + 2 ;; pid of the new client process<br> + (sin 10) = -0.5440211108893699 ;; result<br> + &gt; (trig-client server-pid 'cos 1.2)<br> + 3<br> + (cos 1.2) = 0.3623577544766736<br> + <br> + }}}<br> + <br> + With concurrent objects we have a powerful tool to model the real world in software. Like objects in the real world, Spark processes live and execute independently. They interact with other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming].<br> + <br> + ==== Processes and fault tolerant ====<br> + <br> + A system is ''fault tolerant'' if it can detect errors and repair itself. Spark process can have fault tolerance with the help of ''watcher'' processes. A ''watcher'' process is notified by the system when a ''watched'' process dies or exits. The following code snippet introduces the procedure ''watch'' that enables a process to keep an eye on another process:<br> + <br> + {{{<br> + <br> + (define (test-server pid)<br> + (let loop ((m (receive pid)))<br> + (if (not (eq? m 'exit))<br> + (loop (receive pid)))))<br> + <br> + (define (watch-server server-pid)</span> </td> </tr> <tr> <td> Line 242: </td> <td> Line 157: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 244: </td> <td> Line 158: </td> </tr> <tr> <td> <span>- <br> - (send server-pid (list pid func val))<br> - <br> - (printf "(~a ~a) = ~a" func val (receive pid))<br> - <br> - (flush-output))))<br> - <br> - <br> - <br> - }}}<br> - <br> - <br> - <br> - To try our changed code, you need to load both trig-server.ss and trig-client.ss to the Spark environment.<br> - <br> - <br> - <br> - {{{<br> - <br> - <br> - <br> - &gt; (load "trig-server.ss")<br> - <br> - &gt; (load "trig-client.ss")<br> - <br> - &gt; (define server-pid (spawn trig-server))<br> - <br> - &gt; (trig-client server-pid 'sin 10)<br> - <br> - 2 ;; pid of the new client process<br> - <br> - (sin 10) = -0.5440211108893699 ;; result<br> - <br> - &gt; (trig-client server-pid 'cos 1.2)<br> - <br> - 3<br> - <br> - (cos 1.2) = 0.3623577544766736<br> - <br> - <br> - <br> - }}}<br> - <br> - <br> - <br> - With concurrent objects we have a powerful tool to model the real world in software. Like objects in the real world, Spark processes live and execute independently. They interact with other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming].<br> - <br> - <br> - <br> - ==== Processes and fault tolerant ====<br> - <br> - <br> - <br> - A system is ''fault tolerant'' if it can detect errors and repair itself. Spark process can have fault tolerance with the help of ''watcher'' processes. A ''watcher'' process is notified by the system when a ''watched'' process dies or exits. The following code snippet introduces the procedure ''watch'' that enables a process to keep an eye on another process:<br> - <br> - <br> - <br> - {{{<br> - <br> - <br> - <br> - (define (test-server pid)<br> - <br> - (let loop ((m (receive pid)))<br> - <br> - (if (not (eq? m 'exit))<br> - <br> - (loop (receive pid)))))<br> - <br> - <br> - <br> - <br> - <br> - (define (watch-server server-pid)<br> - <br> - (spawn<br> - <br> - (lambda (pid)<br> - </span> </td> <td> </td> </tr> <tr> <td> Line 324: </td> <td> Line 159: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 326: </td> <td> Line 160: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 328: </td> <td> Line 161: </td> </tr> <tr> <td> <span>- <br> - </span> (if (eq? (car m) 'dead)<span><br> - </span> </td> <td> <span>+</span> (if (eq? (car m) 'dead) </td> </tr> <tr> <td> Line 332: </td> <td> Line 163: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 334: </td> <td> Line 164: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 336: </td> <td> Line 165: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 339: </td> <td> Line 167: </td> </tr> <tr> <td> <span>- <br> - <br> - }}}<br> - <br> - </span> </td> <td> <span>+ }}}</span> </td> </tr> <tr> <td> Line 347: </td> <td> Line 171: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ {{{</span> </td> </tr> <tr> <td> Line 354: </td> <td> Line 174: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 356: </td> <td> Line 175: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 358: </td> <td> Line 176: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 360: </td> <td> Line 177: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 362: </td> <td> Line 178: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 364: </td> <td> Line 179: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 366: </td> <td> Line 180: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 368: </td> <td> Line 181: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 371: </td> <td> Line 183: </td> </tr> <tr> <td> <span>- <br> - <br> - }}}<br> - <br> - </span> </td> <td> <span>+ }}}</span> </td> </tr> <tr> <td> Line 379: </td> <td> Line 187: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 383: </td> <td> Line 189: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 386: </td> <td> Line 190: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 388: </td> <td> Line 191: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 390: </td> <td> Line 192: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 392: </td> <td> Line 193: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 394: </td> <td> Line 194: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 397: </td> <td> Line 196: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 400: </td> <td> Line 197: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 403: </td> <td> Line 199: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 407: </td> <td> Line 201: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 411: </td> <td> Line 203: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ {{{</span> </td> </tr> <tr> <td> Line 418: </td> <td> Line 206: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 420: </td> <td> Line 207: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 422: </td> <td> Line 208: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 424: </td> <td> Line 209: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 426: </td> <td> Line 210: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 430: </td> <td> Line 211: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 432: </td> <td> Line 212: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 436: </td> <td> Line 213: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 438: </td> <td> Line 214: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 441: </td> <td> Line 216: </td> </tr> <tr> <td> <span>- <br> - <br> - }}}<br> - <br> - </span> </td> <td> <span>+ }}}</span> </td> </tr> <tr> <td> Line 448: </td> <td> Line 219: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 451: </td> <td> Line 221: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 455: </td> <td> Line 223: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - </span> </td> <td> <span>+ {{{</span> </td> </tr> <tr> <td> Line 462: </td> <td> Line 226: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 464: </td> <td> Line 227: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 467: </td> <td> Line 229: </td> </tr> <tr> <td> <span>- <br> - <br> - }}}<br> - <br> - </span> </td> <td> <span>+ }}}</span> </td> </tr> <tr> <td> Line 475: </td> <td> Line 233: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 479: </td> <td> Line 235: </td> </tr> <tr> <td> <span>- <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 483: </td> <td> Line 237: </td> </tr> <tr> <td> <span>- <br> - <br> - {{{<br> - <br> - <br> - <br> - ;; BAD!!<br> - </span> </td> <td> <span>+ {{{<br> + <br> + ;; Global state is BAD!!</span> </td> </tr> <tr> <td> Line 492: </td> <td> Line 241: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 496: </td> <td> Line 242: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 498: </td> <td> Line 243: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 500: </td> <td> Line 244: </td> </tr> <tr> <td> <span>- <br> - <br> - </span> </td> <td> </td> </tr> <tr> <td> Line 504: </td> <td> Line 245: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 506: </td> <td> Line 246: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 508: </td> <td> Line 247: </td> </tr> <tr> <td> <span>- </span> </td> <td> </td> </tr> <tr> <td> Line 511: </td> <td> Line 249: </td> </tr> <tr> <td> <span>- <br> - <br> - }}}<br> - <br> - </span> </td> <td> <span>+ }}}</span> </td> </tr> </table> </div> Concurrencyhttp://spark-scheme.wikispot.org/Concurrency2009-05-01 12:29:50vijaymathew <div id="content" class="wikipage content"> Differences for Concurrency<p><strong></strong></p><table> <tr> <td> <span> Deletions are marked with - . </span> </td> <td> <span> Additions are marked with +. </span> </td> </tr> <tr> <td> Line 1: </td> <td> Line 1: </td> </tr> <tr> <td> </td> <td> <span>+ == Concurrency ==<br> + <br> + <br> + <br> + [#processes Concurrent objects or Processes]<br> + <br> + [#asyncprocs Asynchronous Procedures]<br> + <br> + [#threads Threads]<br> + <br> + <br> + <br> + [[Anchor(processes)]]<br> + <br> + === Concurrent objects or Processes ===<br> + <br> + <br> + <br> + Spark allows several computations to execute simultaneously, possibly interacting with each other. In programming parlance this is known as multi-processing, multi-threading, concurrency etc. Programming languages usually depend on the host operating systems capabilities to implement concurrency. Spark has built-in concurrency. It provide multi-threading without any help from the underlying operating system. This has some important consequences:<br> + <br> + <br> + <br> + * Concurrent objects (or processes) behave the same on all operating systems.<br> + <br> + * They are not subject to any system imposed limitations. You can have as many concurrent objects as you want.<br> + <br> + <br> + <br> + To write concurrent programs, we need to become familiar with three new procedures: ''spawn'', ''send'' and ''receive''.<br> + <br> + <br> + <br> + '''(spawn proc)''': Creates a new process that evaluates the procedure ''proc''. The return value is an integer that identifies the process. It takes an optional arguments which can be used to initialize the state of the new process.<br> + <br> + <br> + <br> + '''(send pid)''': Sends a message to the process identified by ''pid''. Message sending is asynchronous.<br> + <br> + <br> + <br> + '''(receive pid)''': Receives a message from the message queue of the process identified by ''pid''. Calls to ''receive'' usually make use of the pattern matching facility provided by the ''match'' library and has the following coding pattern:<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + (import (match))<br> + <br> + <br> + <br> + (define (process-callback pid)<br> + <br> + (let ((msg (receive pid)))<br> + <br> + ;; Match the message against a set of patterns.<br> + <br> + (match msg<br> + <br> + ((pattern1) expressions1)<br> + <br> + ((pattern2) expressions2)<br> + <br> + ((_) handle-unexpected-message))))<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + Let us try to get a better understanding of concurrent objects with the help of a simple example. Here we define an object that can act as background service for doing trigonometric calculations. It waits for messages in a loop. A message is packed as a list data structure with the first element identifying the trigonometric function to execute and the rest of the elements being it's arguments. When a message arrives, it is unpacked using the ''match'' procedure and an appropriate trigonometric function is executed and the result is displayed. If it receives the special message 'exit, the concurrent object kills itself.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + ;; file: trig-server.ss<br> + <br> + <br> + <br> + (import (match))<br> + <br> + <br> + <br> + (define (trig-server pid)<br> + <br> + (let loop ((message (receive pid)))<br> + <br> + (cond<br> + <br> + ((not (eq? message 'exit))<br> + <br> + (match message<br> + <br> + (('sin a)<br> + <br> + (printf "sin of ~a is ~a~n" a (sin a)))<br> + <br> + (('cos a)<br> + <br> + (printf "cos of ~a is ~a~n" a (cos a)))<br> + <br> + (('tan a)<br> + <br> + (printf "tan of ~a is ~a~n" a (tan a)))<br> + <br> + (_<br> + <br> + (printf "Don't know the trig function ~a~n" message)))<br> + <br> + (loop (receive pid)))<br> + <br> + (else<br> + <br> + (display "Goodbye.")<br> + <br> + (newline)))))<br> + <br> + }}}<br> + <br> + <br> + <br> + To use the ''trig server'', load ''trig-server.ss'' into Spark and spawn a process with the procedure ''trig-server'' as it's callback.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (load "trig-server.ss")<br> + <br> + &gt; (define pid (spawn trig-server))<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + Now we can send messages to the trigonometry object and have the results printed. As this object lives in it's own parallel world, we can go on with our business as it does the computations.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (send pid (list 'sin 3.4))<br> + <br> + sin of 3.4 is -0.2555411020268312<br> + <br> + &gt; (send pid (list 'cos 2.1))<br> + <br> + cos of 2.1 is -0.5048461045998575<br> + <br> + &gt; (send pid (list 'tan 3.5))<br> + <br> + tan of 3.5 is 0.3745856401585947<br> + <br> + &gt; (send pid (list 'blah 7))<br> + <br> + Don't know the trif function (blah 7)<br> + <br> + &gt; (send pid 'exit)<br> + <br> + Goodbye.<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + Let us extend the trig-server with a complete implementation of inter-process communication. The sending process should include it's process id as the first element of the message. ''trig-server'' will compute the result and send it back to that process.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + (import (match))<br> + <br> + <br> + <br> + (define (trig-server pid)<br> + <br> + (let loop ((message (receive pid)))<br> + <br> + (cond<br> + <br> + ((not (eq? message 'exit))<br> + <br> + (match message<br> + <br> + ((sender-pid 'sin a)<br> + <br> + (send sender-pid (sin a)))<br> + <br> + ((sender-pid 'cos a)<br> + <br> + (send sender-pid (cos a)))<br> + <br> + ((sender-pid 'tan a)<br> + <br> + (send sender-pid (tan a)))<br> + <br> + (_<br> + <br> + (printf "Don't know the trig function ~a~n" message)))<br> + <br> + (loop (receive pid)))<br> + <br> + (else<br> + <br> + (display "Goodbye.")<br> + <br> + (newline)))))<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + Here is a client process that can interact with the ''trig-server''. It is wrapped up in a procedure that takes the server process id, the trig function and it's argument as it's parameters. Internally we spawn a new process that will send the request to the server get the response and print it.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + (define (trig-client server-pid func val)<br> + <br> + (spawn<br> + <br> + (lambda (pid)<br> + <br> + (send server-pid (list pid func val))<br> + <br> + (printf "(~a ~a) = ~a" func val (receive pid))<br> + <br> + (flush-output))))<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + To try our changed code, you need to load both trig-server.ss and trig-client.ss to the Spark environment.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (load "trig-server.ss")<br> + <br> + &gt; (load "trig-client.ss")<br> + <br> + &gt; (define server-pid (spawn trig-server))<br> + <br> + &gt; (trig-client server-pid 'sin 10)<br> + <br> + 2 ;; pid of the new client process<br> + <br> + (sin 10) = -0.5440211108893699 ;; result<br> + <br> + &gt; (trig-client server-pid 'cos 1.2)<br> + <br> + 3<br> + <br> + (cos 1.2) = 0.3623577544766736<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + With concurrent objects we have a powerful tool to model the real world in software. Like objects in the real world, Spark processes live and execute independently. They interact with other using messages. As they need not share memory, programs can be written without worrying about synchronization and locks. Spark's concurrent objects are an implementation of the [http://en.wikipedia.org/wiki/Actor_model Actor model] and brings the experienced programmer to a previously intimacy with pure [http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en Object Oriented Programming].<br> + <br> + <br> + <br> + ==== Processes and fault tolerant ====<br> + <br> + <br> + <br> + A system is ''fault tolerant'' if it can detect errors and repair itself. Spark process can have fault tolerance with the help of ''watcher'' processes. A ''watcher'' process is notified by the system when a ''watched'' process dies or exits. The following code snippet introduces the procedure ''watch'' that enables a process to keep an eye on another process:<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + (define (test-server pid)<br> + <br> + (let loop ((m (receive pid)))<br> + <br> + (if (not (eq? m 'exit))<br> + <br> + (loop (receive pid)))))<br> + <br> + <br> + <br> + <br> + <br> + (define (watch-server server-pid)<br> + <br> + (spawn<br> + <br> + (lambda (pid)<br> + <br> + (watch server-pid pid)<br> + <br> + (printf "~a watching ~a~n" pid server-pid)<br> + <br> + (let loop ((m (receive pid)))<br> + <br> + (if (eq? (car m) 'dead)<br> + <br> + (begin<br> + <br> + (printf "Process ~a is dead. Restarting it ...~n" (cdr m))<br> + <br> + (watch-server (spawn test-server)))<br> + <br> + (loop (receive pid)))))))<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + The process represented by ''test-server'' can be brought under watch by passing it's proc-id to ''watch-server''. When it dies, it is restarted by the watcher. This is demonstrated in the following session:<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (watch-server (spawn test-server))<br> + <br> + 2<br> + <br> + 2 watching 1<br> + <br> + &gt; (send 1 'exit)<br> + <br> + Process (1) is dead. Restarting it ...<br> + <br> + 4 watching 3<br> + <br> + &gt; (send 3 'exit)<br> + <br> + Process (3) is dead. Restarting it ...<br> + <br> + 6 watching 5<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + '''Exercise 1: ''' Modify the procedure ''watch-server'' so that the same watcher process is re-used to watch all new ''test-server'' processes.<br> + <br> + <br> + <br> + Here are a few useful process utility procedures:<br> + <br> + <br> + <br> + '''(kill proc-id)''': Forcefully kills the process identified by ''proc-id''.<br> + <br> + '''(alive? proc-id)''': Returns #t if the process identified by ''proc-id'' is alive.<br> + <br> + '''(register proc-id name)''': Maps ''name'' to ''proc-id''. After registering the name, it can be used instead of ''proc-id'' in ''send'' calls.<br> + <br> + '''(unregister proc-id name)''': Removes the ''proc-id'' to ''name'' mapping from the system.<br> + <br> + '''(descriptor proc-id)''': Returns the thread descriptor object that the process internally uses.<br> + <br> + '''(message-channel proc-id)''': Returns the asynchronous message channel object that the process internally uses.<br> + <br> + <br> + <br> + [[Anchor(asyncprocs)]]<br> + <br> + === Asynchronous procedures ===<br> + <br> + <br> + <br> + An asynchronous procedures can be used to get a time consuming computation done in the background. It is another way of creating processes without the messaging infrastructure. You define the computation as a procedure and invoke it with a call to ''async''.<br> + <br> + <br> + <br> + '''(async proc args-list callback-proc)''': ''proc'' is the procedure to be executed asynchronously. ''args-list'' is a list of arguments that will be passed to ''proc''. This should be null if ''proc'' does not take any arguments. ''callback-proc'' is a procedure that will be called once ''proc'' is done. ''called-proc'' will receive as it's argument the value that ''proc'' evaluates to. ''called-proc'' can be null.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (define (long-computation a b)<br> + <br> + ;; We simulate the long computation by<br> + <br> + ;; making the current thread of execution sleep for 2 seconds.<br> + <br> + (sleep 2)<br> + <br> + (+ a b))<br> + <br> + <br> + <br> + &gt; (define (done-callback result)<br> + <br> + (printf "long computation done. result is ~a~n" result))<br> + <br> + <br> + <br> + &gt; (async long-computation (list 10 20) done-callback)<br> + <br> + &gt;<br> + <br> + long computation done. result is 30<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + [[Anchor(threads)]]<br> + <br> + === Threads ===<br> + <br> + <br> + <br> + If you have programmed in languages like Java or Python, you might have used ''threads'' to simulate concurrency. Spark too have threads. But unlike the aforementioned languages, Spark's multi-threading capabilities are not dependent on the host operating system. Threads is part of the Spark runtime itself. A new thread is created with a call to the ''thread'' procedure. It takes a procedure as it's argument, which will be execute in the new thread. The return value is a thread descriptor object.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + &gt; (thread (lambda () (display "i am in a new thread!") (newline)))<br> + <br> + #&lt;thread&gt;<br> + <br> + i am in a new thread!<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + See the MzScheme documentation for more information on threads.<br> + <br> + <br> + <br> + ==== Atomic operations ====<br> + <br> + <br> + <br> + The preferred paradigm for Spark is [http://www.defmacro.org/ramblings/fp.html Functional Programming]. ''(see the section on Concurrency)''. Spark is not a pure functional language. It means that there is nothing in the language that ''prevents'' you from sharing state across processes. If two processes modify a shared resource at the same time, that might lead to data corruption and incorrect program behavior. Spark provides the special form ''atomic'' to prevent a piece of code from being executed by two processes at the same time. If the portion of code that writes to the shared state is ''atomic'', it is guaranteed that it won't be modified by two processes at the same time.<br> + <br> + <br> + <br> + {{{<br> + <br> + <br> + <br> + ;; BAD!!<br> + <br> + &gt; (define global-state 0)<br> + <br> + <br> + <br> + &gt; (define (modify-global-state)<br> + <br> + (atomic<br> + <br> + (set! global-state (add1 global-state))))<br> + <br> + <br> + <br> + &gt; (async modify-global-state)<br> + <br> + &gt; (async modify-global-state)<br> + <br> + &gt; global-state<br> + <br> + 2<br> + <br> + <br> + <br> + }}}<br> + <br> + <br> + <br> + The atomic block in ''modify-global-state'' makes sure that all writes to ''global-state'' is serialized.</span> </td> </tr> </table> </div>