Many programming languages that support concurrency offer communication channels that allow the exchange of values between processes or threads running concurrently in a system. Communications established between processes may follow a specific protocol, requiring the programmer to write functions to establish the required pattern of communication. Meanwhile, a communicating system often requires establishing multiple channels, such as to multiple servers, and then choosing between the available channels when new data is available. This can be accomplished using polling, such as with the select operation on Unix systems. Combining both application-specific protocols and multi-party communication may be complicated due to the need to introduce polling and checking for blocking within a pre-existing protocol. Concurrent ML solves this problem by reducing this coupling of programming concepts by introducing synchronizable events. Events are a first-class abstraction that can be used with a synchronization operation in order to potentially block and then produce some value resulting from communication. In CML, events can be combined or manipulated using a number of primitive operations. Each primitive operation constructs a new event rather than modifying the event in-place, allowing for the construction of compound events that represent a desired communication pattern. For example, CML allows the programmer to combine several sub-events in order to create a compound event that can then make a non-deterministic choice of one of the sub-events. Another primitive creates a new event that will modify the value resulting from synchronization on the original event. These events embody patterns of communication that, in a non-CML language, would typically be handled using a polling loop or function with handlers for each kind of event.
Sample Code
Here is sample code to print "hello, world" to the console. It spawns a thread which creates a channel for strings. This thread then spawns another thread which prints the first string that is received on the channel. The former thread then sends the "hello, world\n" string on the channel. It uses SML/NJ and CML : ;cml_test.cm: Library structure Hello is $cml/basis.cm $cml/cml.cm cml_test.sml ;cml_test.sml: structure Hello = struct open CML
fun hello = letval c : string chan = channel in spawn => TextIO.print ); send ; exit end
fun main = RunCML.doit => ignore end ;Running: $ ml-build cml_test.cm Hello.main Standard ML of New Jersey v110.60 $ heap2exec cml_test.x86-linux cml_test $./cml_test hello, world