/*******************************************************************************
* Copyright (c) 2013 Imperial College London.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raul Castro Fernandez - initial design and implementation
******************************************************************************/
package uk.ac.imperial.lsds.seep.runtimeengine;
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Phaser;
import java.util.concurrent.SynchronousQueue;
import uk.ac.imperial.lsds.seep.comm.serialization.DataTuple;
/**
* Reason why the barrier is implemented with the Phaser of Java 7 instead of a common CyclicBarrier of previous java is because of its robust support
* for dynamicity. Only this feature justified changing the version of the language.
* **/
public class Barrier implements DataStructureI {
private Phaser staticBarrier;
private ArrayList<DataTuple> data = new ArrayList<DataTuple>();
private BlockingQueue<ArrayList<DataTuple>> sbq = new SynchronousQueue<ArrayList<DataTuple>>();
private long lastTimestamp = 0;
private int repetitions = 0;
private int repetitionsANN = 0 ;
private long cummulatedTime = 0;
private long cummulatedBarrierTime = 0 ;
private long barrierTimeEachPhase;
public Barrier(int initialNumberOfThreads){
staticBarrier = new Phaser(initialNumberOfThreads){
protected boolean onAdvance(int phase, int parties) {
cummulatedBarrierTime += (System.nanoTime() - barrierTimeEachPhase);
long now = System.currentTimeMillis();
if(lastTimestamp != 0){
cummulatedTime += (now-lastTimestamp);
lastTimestamp = now;
repetitions++;
repetitionsANN++;
if(repetitions == 5000){
System.out.println("AVG barrier time: "+(cummulatedTime)+" ms");
repetitions = 0;
cummulatedTime = 0;
}
if(repetitionsANN == 9500){
System.out.println("Accum barrier time: "+((double)(cummulatedBarrierTime/1000000000.0))+" s");
System.out.println("repetitions = " + repetitionsANN);
repetitionsANN = 0 ;
cummulatedBarrierTime = 0 ;
}
}
else{
lastTimestamp = now;
}
ArrayList<DataTuple> copy = new ArrayList<DataTuple>(data);
data.clear();
try {
sbq.put(copy);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
};
}
public void reconfigureBarrier(int numThreads){
// Dynamic tiering of the hierarchical phaser
// Check the num of Threads.
// If it hits a given threshold (static or dynamic)
// partition the parties into two phasers
// register those in the master one
staticBarrier.register();
// staticBarrier.bulkRegister(numThreads);
}
@Override
public DataTuple pull() {
return null;
}
public ArrayList<DataTuple> pull_from_barrier(){
ArrayList<DataTuple> toRet = null;
try {
toRet = sbq.take();
}
catch (InterruptedException e) {
e.printStackTrace();
}
return toRet;
}
@Override
public void push(DataTuple dt) {
// We put the data
synchronized(data){
data.add(dt);
if( (data.size() == 1) ){
barrierTimeEachPhase = System.nanoTime();
}
}
try{
// And wait on the barrier
staticBarrier.arriveAndAwaitAdvance();
}
catch(IllegalStateException ise){
///\fixme{Register in advance, dont force the exception}
staticBarrier.register();
staticBarrier.arriveAndAwaitAdvance();
}
}
}