crazy4groovy
4/17/2014 - 7:30 PM

piapprox.groovy

import groovy.transform.*
import groovyx.gpars.actor.*
import groovyx.gpars.group.*

@Immutable class Calculate {}
@Immutable class Work { int start, nrOfElements }
@Immutable class Result { double value }
@Immutable class PiApproximation { double pi ; long duration }

double calculatePiFor( int start, int nrOfElements ) {
    ((start * nrOfElements)..((start + 1) * nrOfElements - 1)).inject( 0.0 ) { acc, i ->
        acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
    }
}

def group = new DefaultPGroup()

def listener = group.actor {
    loop {
        react {
            println "Pi approx $it.pi in $it.duration"
            terminate()
        }
    }
}

int nrOfWorkers  = 4
int nrOfMessages = 1000
int nrOfElements = 1000

def workers = (1..nrOfWorkers).collect {
    group.actor {
        loop {
            react {
                reply new Result( calculatePiFor( it.start, it.nrOfElements ) )
            }
        }
    }
}

double pi = 0.0
int nrOfResults = 0
long start = System.currentTimeMillis()

def master = group.actor {
    loop {
        react {
            switch( it ) {
                case Calculate:
                    nrOfMessages.times { i -> workers[ i % nrOfWorkers ].send( new Work( i, nrOfElements ) ) }
                    break
                case Result:
                    pi += it.value
                    if( ++nrOfResults >= nrOfMessages ) {
                        listener.send( new PiApproximation( pi, System.currentTimeMillis() - start ) )
                        workers*.terminate()
                        terminate()
                    }
                    break
            }
        }
    }
}

master << new Calculate()
master.join()