F Sharp Programming/MailboxProcessor

F#'s MailboxProcessor class is essentially a dedicated message queue running on its own logical thread of control. Any thread can send the MailboxProcessor a message asynchronously or synchronously, allowing threads to communicate between one another through message passing. The "thread" of control is actually a lightweight simulated thread implemented via asynchronous reactions to messages. This style of message-passing concurrency is inspired by the Erlang programming language.

Defining MailboxProcessors
MailboxProcessors are created using the MailboxProcessor.Start method which has the type :

The value  has the type   and represents the message queue. The method  dequeues the first message from the message queue and binds it to the   identifier. If there are no messages in queue,  releases the thread back to the threadpool and waits for further messages. No threads are blocked while  waits for further messages.

We can experiment with  in fsi:

MailboxProcessor Methods
There are several useful methods in the MailboxProcessor class:

 
 * Create and start an instance of a MailboxProcessor. The asynchronous computation executed by the processor is the one returned by the 'initial' function.

 
 * Post a message to the message queue of the MailboxProcessor, asynchronously.

 
 * Post a message to the message queue of the MailboxProcessor and await a reply on the channel. The message is produced by a single call to the first function which must build a message containing the reply channel. The receiving MailboxProcessor must process this message and invoke the Reply method on the reply channel precisely once.

 
 * Return an asynchronous computation which will consume the first message in arrival order. No thread is blocked while waiting for further messages. Raise a TimeoutException if the timeout is exceeded.

Two-way Communication
Just as easily as we can send messages to MailboxProcessors, a MailboxProcessor can send replies back to consumers. For example, we can interrogate the value of a MailboxProcessor using the  method as follows:

The  union wraps two types of messages: we can tell the MailboxProcessor to increment, or have it send its contents to a reply channel. The type  exposes a single method,. We can use this class in fsi as follows:

Notice that  is a syncronous method.

Encapsulating MailboxProcessors with Objects
Often, we don't want to expose the implementation details of our classes to consumers. For example, we can re-write the example above as a class which exposes a few select methods:

Prime Number Sieve
Rob Pike delivered a fascinating presentation at a Google TechTalk on the NewSqueak programming language. NewSqueak's approach to concurrency uses channels, analogous to MailboxProcessors, for inter-thread communication. Toward the end of the presentation, he demonstrates how to implement a prime number sieve using these channels. The following is an implementation of prime number sieve based on Pike's NewSqueak code:

represents an infinite list of numbers from n..infinity.

is simply a filter for another MailboxProcessor. Its analogous to.

is essentially an iterative filter: we seed our prime list with the first prime,  and a infinite list of numbers from 3..infinity. Each time we process a message, we return the prime number, then replace our infinite list with a new list which filters out all numbers divisible by our prime. The head of each new filtered list is the next prime number.

So, the first time we call, we get back a 2 and replace our infinite list with all numbers not divisible by two. We call next again, we get back the next prime, 3, and filter our list again for all numbers divisible by 3. We call next again, we get back the next prime, 5 (we skip 4 since its divisible by 2), and filter all numbers divisible by 5. This process repeats indefinitely. The end result is a prime number sieve with an identical implementation to the Sieve of Eratosthenes. We can test this class in fsi: