Concurrent Prime Sieve in Clojure
While watching the Go Concurrency Patterns talk by Rob Pike, I came across a Concurrent Prime Sieve implementation in Go which Rob had claimed to be beautiful concurrent code. Curious enough, I checked out the example and decided on implementing it in Clojure.
Let’s begin by creating an infinite sequence generator(starting from 2):
|
|
The go
block ensures that the body is run on a seperate thread. I used the
blocking put instead of the parking one to only generate a number when required
by the program. Had I used the parking put >!
instead, we would’ve encountered
the OutOfMemory
exception while executing the function.
Let’s test this generator:
|
|
Not the best way to test of course, but it seems to work as expected.
Next, let’s write a filter function that takes an input channel, an output channel and a value, and filters out the non-prime numbers from the input channel before sending them to the output channel. This is what the “prime sieve” refers to.
|
|
Before testing filter-prime
, let’s tie the above two functions together
with the user input using fetch-prime
:
|
|
And, finally test to see if it works:
|
|
The whole process can be visualised as a bunch of sieves lined up on top of each
other vertically with the numbers from the generator passing through
them. Essentially, each sieve is a filter-prime
with the last prime
val
passed as it’s parameter. At any pass, if the modulus value is zero,
the number (retrieved from the generator) in that pass is discarded.
Though this took me a bit of head banging, in the end, I got a much better picture of the concurreny model using go blocks in Clojure. The way in which different threads communicate with each other as a Daisy Chain filter to remove the non-primes makes this a neat example for demonstrating concurrency.