Concurrent ML

Last updated
Concurrent ML
Paradigm Concurrent computing
Family ML
First appeared1991;33 years ago (1991) [1]
Website http://cml.cs.uchicago.edu/
Major implementations
SML/NJ, [2] MLton, [3] Manticore [4]

Concurrent ML (CML) is a concurrent extension of the Standard ML programming language, characterized by its ability to allow programmers to create composable communication abstractions that are first-class rather than built into the language. The design of CML and its primitive operations have been adopted in several other programming languages, such as GNU Guile, [5] Racket, [6] and Manticore. [4]

Contents

Concepts

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. [7] Events are a first-class abstraction that can be used with a synchronization operation (called sync in CML and Racket) in order to potentially block and then produce some value resulting from communication (for example, data transmitted on a channel).

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 the 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 to 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.

Hello world

Here is a program that prints "Hello, world!" to the console. It spawns one thread with a channel for strings, and another thread which prints a string received on the channel. It uses SML/NJ and CML. (Note that the heap name will be different on non linux-x86 platforms; you may need to change the line with "cml_test.x86-linux" to something different.)

cml_test.cm
LibrarystructureHellois$cml/basis.cm$cml/cml.cmcml_test.sml
cml_test.sml
structureHello=structopenCMLfunhello()=letvalc:stringchan=channel()inspawn(fn()=>TextIO.print(recvc));send(c,"Hello, world!\n");exit()endfunmain(_,argv)=RunCML.doit(fn()=>ignore(spawnhello),NONE)end
bash
$ ml-buildcml_test.cmHello.main Standard ML of New Jersey v110.60 [built: Mon Nov 27 14:19:21 2006][scanning cml_test.cm][library $cml/basis.cm is stable][library $cml/cml.cm is stable][parsing (cml_test.cm):cml_test.sml][creating directory .cm/SKEL][library $cml/cml-internal.cm is stable][library $cml/core-cml.cm is stable][library $SMLNJ-BASIS/basis.cm is stable][compiling (cml_test.cm):cml_test.sml][creating directory .cm/GUID][creating directory .cm/x86-unix][code: 2170, data: 42, env: 2561 bytes][scanning 18518-export.cm][scanning (18518-export.cm):cml_test.cm][parsing (18518-export.cm):18518-export.sml][compiling (18518-export.cm):18518-export.sml][code: 309, data: 37, env: 42 bytes]$ heap2execcml_test.x86-linuxcml_test $ ./cml_test Hello, world!

Related Research Articles

<span class="mw-page-title-main">Thread (computing)</span> Smallest sequence of programmed instructions that can be managed independently by a scheduler

In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system. In many cases, a thread is a component of a process.

<span class="mw-page-title-main">System call</span> Way for programs to access kernel services

In computing, a system call is the programmatic way in which a computer program requests a service from the operating system on which it is executed. This may include hardware-related services, creation and execution of new processes, and communication with integral kernel services such as process scheduling. System calls provide an essential interface between a process and the operating system.

Coroutines are computer program components that allow execution to be suspended and resumed, generalizing subroutines for cooperative multitasking. Coroutines are well-suited for implementing familiar program components such as cooperative tasks, exceptions, event loops, iterators, infinite lists and pipes.

In computer science, a lock or mutex is a synchronization primitive that prevents state from being modified or accessed by multiple threads of execution at once. Locks enforce mutual exclusion concurrency control policies, and with a variety of possible methods there exist multiple unique implementations for different applications.

<span class="mw-page-title-main">Race condition</span> When a systems behavior depends on timing of uncontrollable events

A race condition or race hazard is the condition of an electronics, software, or other system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events, leading to unexpected or inconsistent results. It becomes a bug when one or more of the possible behaviors is undesirable.

In computer science, compare-and-swap (CAS) is an atomic instruction used in multithreading to achieve synchronization. It compares the contents of a memory location with a given value and, only if they are the same, modifies the contents of that memory location to a new given value. This is done as a single atomic operation. The atomicity guarantees that the new value is calculated based on up-to-date information; if the value had been updated by another thread in the meantime, the write would fail. The result of the operation must indicate whether it performed the substitution; this can be done either with a simple boolean response, or by returning the value read from the memory location.

In computing, a memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction. This typically means that operations issued prior to the barrier are guaranteed to be performed before operations issued after the barrier.

<span class="mw-page-title-main">Linearizability</span> Property of some operation(s) in concurrent programming

In concurrent programming, an operation is linearizable if it consists of an ordered list of invocation and response events, that may be extended by adding response events such that:

  1. The extended list can be re-expressed as a sequential history.
  2. That sequential history is a subset of the original unextended list.

In computer science, asynchronous I/O is a form of input/output processing that permits other processing to continue before the I/O operation has finished. A name used for asynchronous I/O in the Windows API is overlapped I/O.

In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.

In computing, a parallel programming model is an abstraction of parallel computer architecture, with which it is convenient to express algorithms and their composition in programs. The value of a programming model can be judged on its generality: how well a range of different problems can be expressed for a variety of different architectures, and its performance: how efficiently the compiled programs can execute. The implementation of a parallel programming model can take the form of a library invoked from a sequential language, as an extension to an existing language, or as an entirely new language.

Concurrent computing is a form of computing in which several computations are executed concurrently—during overlapping time periods—instead of sequentially—with one completing before the next starts.

In computer science and engineering, transactional memory attempts to simplify concurrent programming by allowing a group of load and store instructions to execute in an atomic way. It is a concurrency control mechanism analogous to database transactions for controlling access to shared memory in concurrent computing. Transactional memory systems provide high-level abstraction as an alternative to low-level thread synchronization. This abstraction allows for coordination between concurrent reads and writes of shared data in parallel systems.

In computer science, a readers–writer is a synchronization primitive that solves one of the readers–writers problems. An RW lock allows concurrent access for read-only operations, whereas write operations require exclusive access. This means that multiple threads can read the data in parallel but an exclusive lock is needed for writing or modifying data. When a writer is writing the data, all other writers and readers will be blocked until the writer is finished writing. A common use might be to control access to a data structure in memory that cannot be updated atomically and is invalid until the update is complete.

In computer science, synchronization is the task of coordinating multiple of processes to join up or handshake at a certain point, in order to reach an agreement or commit to a certain sequence of action.

In computer programming, a green thread is a thread that is scheduled by a runtime library or virtual machine (VM) instead of natively by the underlying operating system (OS). Green threads emulate multithreaded environments without relying on any native OS abilities, and they are managed in user space instead of kernel space, enabling them to work in environments that do not have native thread support.

The Java programming language and the Java virtual machine (JVM) is designed to support concurrent programming. All execution takes place in the context of threads. Objects and resources can be accessed by many separate threads. Each thread has its own path of execution, but can potentially access any object in the program. The programmer must ensure read and write access to objects is properly coordinated between threads. Thread synchronization ensures that objects are modified by only one thread at a time and prevents threads from accessing partially updated objects during modification by another thread. The Java language has built-in constructs to support this coordination.

In computing, a channel is a model for interprocess communication and synchronization via message passing. A message may be sent over a channel, and another process or thread is able to receive messages sent over a channel it has a reference to, as a stream. Different implementations of channels may be buffered or not, and either synchronous or asynchronous.

Alice ML is a programming language designed by the Programming Systems Laboratory at Saarland University, Saarbrücken, Germany. It is a dialect of Standard ML, augmented with support for lazy evaluation, concurrency and constraint programming.

Join-patterns provides a way to write concurrent, parallel and distributed computer programs by message passing. Compared to the use of threads and locks, this is a high level programming model using communication constructs model to abstract the complexity of concurrent environment and to allow scalability. Its focus is on the execution of a chord between messages atomically consumed from a group of channels.

References

  1. Reppy, John H. (June 1991). CML: a Higher-Order Concurrent Language. PLDI.
  2. "What is Standard ML of New Jersey?" . Retrieved April 5, 2021.
  3. "ConcurrentMLImplementation" . Retrieved April 5, 2021.
  4. 1 2 Fluet, Matthew; Bergstrom, Lars; Ford, Nic; Rainey, Mike; Reppy, John; Shaw, Adam; Xiao, Yingqi (May 2009). "Programming in Manticore, a Heterogenous Parallel Functional Language" (PDF). Retrieved July 11, 2018.
  5. Wingo, Andy (June 29, 2017). "A New Concurrent ML" . Retrieved July 11, 2018.
  6. Flatt, Matthew; Findler, Robert Bruce (2004). "Kill-safe synchronization abstractions". Proceedings of the ACM SIGPLAN 2004 conference on Programming language design and implementation. Vol. 39. pp. 47–58. doi:10.1145/996841.996849. ISBN   1581138075. S2CID   5547460.
  7. Reppy, John H. (1993). "Concurrent ML: Design, application and semantics". Functional Programming, Concurrency, Simulation and Automated Reasoning. Lecture Notes in Computer Science. Vol. 693. pp. 165–198. CiteSeerX   10.1.1.50.7965 . doi:10.1007/3-540-56883-2_10. ISBN   978-3-540-56883-4.