Skip to content
Snippets Groups Projects
Commit 952f1fd2 authored by unknown's avatar unknown
Browse files

add FairOrderCycling scheduler + some fixes for MonoThreadedCycling and for philosophers example

parent 1e80c598
No related branches found
No related tags found
No related merge requests found
package example.philosophes;
import mas.core.Cyclable;
import mas.implementation.schedulers.MonoThreadedCycling;
import mas.implementation.schedulers.FairCycling;
import java.util.ArrayList;
import java.util.List;
......@@ -10,7 +10,13 @@ public class MainPhilosophe {
public static void main(String[] args) {
class MyFairCycling extends MonoThreadedCycling<Cyclable> {
int nbCycles = 100;
int nAgents = 100;
/**
* An extension of the scheduler to make some performance tests
*/
class MyFairCycling extends FairCycling<Cyclable> {
long startTimeCycle = 0;
......@@ -22,7 +28,7 @@ public class MainPhilosophe {
@Override
public boolean stopCondition() {
return nbOfCycles == 1000;
return nbOfCycles == nbCycles;
}
@Override
......@@ -41,9 +47,6 @@ public class MainPhilosophe {
}
}
int nAgents = 100;
int nbCycles = 1000;
Philosopher[] philosophers = new Philosopher[nAgents];
Fork[] forks = new Fork[nAgents];
......@@ -60,9 +63,26 @@ public class MainPhilosophe {
philosophers[i].setRightPhilosopher(philosophers[(i+1) % nAgents]);
}
//Sequential execution
sequentialPerformanceTest(100, philosophers);
//Amak execution
MyFairCycling scheduler = new MyFairCycling(philosophers);
scheduler.setSleep(0);
final long startTime = System.nanoTime();
scheduler.start();
scheduler.waitUntilFinish();
final long endTime = System.nanoTime();
System.out.println("AMAk : Total execution time: " + (endTime / 1000 - startTime / 1000) + " microseconds");
System.out.println("\tCycle moyen : " + scheduler.getCycleTime() / 1000 + " microseconds");
}
public static void sequentialPerformanceTest(int nbCycles, Cyclable... cyclables){
final long startTimeSequential = System.nanoTime();
int nbCycle = 0;
......@@ -72,8 +92,8 @@ public class MainPhilosophe {
while(nbCycle < nbCycles){
startTimeCycleSequential = System.nanoTime();
for(Philosopher philosopher : philosophers){
philosopher.cycle();
for(Cyclable cyclable : cyclables){
cyclable.cycle();
}
cycleTimeSequential.add(System.nanoTime() - startTimeCycleSequential);
......@@ -85,15 +105,5 @@ public class MainPhilosophe {
System.out.println("Iterative : Total execution time: " + (endTimeSequential / 1000 - startTimeSequential / 1000) + " microseconds");
System.out.println("\tCycle : " + cycleTimeSequential.stream().mapToLong(value -> value).average().orElse(0.0) /1000 + " microseconds");
final long startTime = System.nanoTime();
scheduler.start();
scheduler.waitUntilFinish();
final long endTime = System.nanoTime();
System.out.println("AMAk : Total execution time: " + (endTime / 1000 - startTime / 1000) + " microseconds");
System.out.println("\tCycle moyen : " + scheduler.getCycleTime() / 1000 + " microseconds");
}
}
......@@ -120,8 +120,11 @@ public class Philosopher extends Agent {
@Override
public void act() {
//System.out.println("Philosopher num " + id + " act");
//Add some complexity to the agent
fibonacciRecursion(23);
scheduler.addCyclable(new Waste(id));
if(scheduler != null){
scheduler.addCyclable(new Waste(id));
}
}
public int fibonacciRecursion(int n){
......
......@@ -3,6 +3,9 @@ package example.philosophes;
import mas.core.Cyclable;
import mas.core.Scheduler;
/**
* This class is useful to see how the scheduler adds new cyclables to the system dynamically.
*/
public class Waste implements Cyclable {
private int id;
......@@ -15,7 +18,7 @@ public class Waste implements Cyclable {
}
@Override
public void cycle() {
/*System.out.println("I'm the waste n°" + id);*/
//System.out.println("I'm the waste n°" + id);
}
@Override
......
package mas.implementation.schedulers;
import mas.core.Cyclable;
import mas.core.Scheduler;
import mas.core.Sleepable;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
/**
* The FairOrderCycling is a one thread scheduler which maintains the same execution order of the cyclables every system's cycle.
*
* @param <T>
* Extended class of {@link mas.core.Cyclable}
*
* @author David Antunes
*/
public class FairOrderCycling<T extends Cyclable> implements Scheduler<T>, Sleepable {
/**
* The cyclable objects handled by the scheduler.
*/
protected List<T> cyclables = new ArrayList<>();
/**
* The cyclables that must be added in the next cycle.
*/
protected Queue<T> pendingToAddCyclables = new ConcurrentLinkedQueue<>();
/**
* The cyclables that must be removed in the next cycle.
*/
protected Queue<T> pendingToRemoveCyclables = new ConcurrentLinkedQueue<>();
/**
* Time between two cycles. Default time in {@link Sleepable#DEFAULT_SLEEP}.
*/
protected int sleep = DEFAULT_SLEEP;
/**
* Number of system cycles.
*/
protected int nbOfCycles = 0;
/**
* Condition to know if the scheduler must be stopped.
*/
protected boolean mustStop = false;
/**
* Condition to know if the scheduler must be paused.
*/
protected boolean mustPause = false;
/**
* Object used to pause the scheduler.
*/
protected CountDownLatch pauseLatch;
/**
* The thread which executes the cycle.
*/
Thread executionThread = new Thread(this::doCycle);
/**
* Constructor which set the initial cyclables.
*
* @param cyclables
* The corresponding cyclables
*/
public FairOrderCycling(T... cyclables){
for(T cyclable : cyclables){
addCyclable(cyclable);
}
}
@Override
public void start() {
executionThread.start();
}
@Override
public void stop() {
mustStop = true;
}
@Override
public void pause() {
if(pauseLatch == null || pauseLatch.getCount() == 0){
pauseLatch = new CountDownLatch(1);
}
mustPause = true;
}
@Override
public void resume() {
if(pauseLatch != null){
pauseLatch.countDown();
}
}
@Override
public void addCyclable(T cyclable) {
cyclable.setScheduler(this);
pendingToAddCyclables.add(cyclable);
}
@Override
public boolean stopCondition() {
return false;
}
@Override
public boolean isFinished() {
return !executionThread.isAlive();
}
@Override
public void waitUntilFinish() {
try {
executionThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public int getSleep() {
return sleep;
}
@Override
public void setSleep(int sleep) {
this.sleep = sleep;
}
@Override
public void doSleep() {
if (getSleep() != 0) {
try {
Thread.sleep(sleep);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Executes {@link #step()} until the scheduler must stop.
*/
protected void doCycle(){
while(!mustStop){
step();
if(stopCondition()){
this.stop();
}
if(mustPause){
try{
pauseLatch.await();
} catch (InterruptedException e){
throw new RuntimeException(e);
}
}
}
}
/**
* Executes a system's cycle.
*/
protected void step(){
onCycleStarts();
treatPendingCyclables();
for(int i = 0; i< cyclables.size(); i++){
T cyclable = cyclables.get(i);
cyclable.cycle();
if(cyclable.terminate()){
pendingToRemoveCyclables.add(cyclable);
}
}
doSleep();
onCycleEnds();
nbOfCycles++;
}
/**
* Add the cyclables that are going to be scheduled on the current cycle and remove those that are not going to be scheduled.
*/
protected void treatPendingCyclables() {
cyclables.removeAll(pendingToRemoveCyclables);
cyclables.addAll(pendingToAddCyclables);
pendingToRemoveCyclables.clear();
pendingToAddCyclables.clear();
}
/**
* This method is called at the end of every system's cycle.
*/
protected void onCycleEnds() {
}
/**
* This method is called at the start of every system's cycle.
*/
protected void onCycleStarts(){
}
/**
* Getter for the number of cycles.
*
* @return the number of cycles performed by the system
*/
public int getNbOfCycles() {
return nbOfCycles;
}
}
package mas.implementation.schedulers;
import mas.core.Cyclable;
import mas.core.Scheduler;
import mas.core.Sleepable;
/**
* Même que MonoThreadedCycling + equitable sur position des Round Robin
*/
public class FairPosCycling implements Scheduler, Sleepable {
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void addCyclable(Cyclable cyclable) {
}
@Override
public int getSleep() {
return 0;
}
@Override
public void setSleep(int sleep) {
}
@Override
public void doSleep() {
}
@Override
public boolean stopCondition() {
return false;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public void waitUntilFinish() {
}
}
......@@ -4,9 +4,7 @@ import mas.core.Cyclable;
import mas.core.Scheduler;
import mas.core.Sleepable;
import java.util.LinkedHashSet;
import java.util.Queue;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
......@@ -25,7 +23,7 @@ public class MonoThreadedCycling<T extends Cyclable> implements Scheduler<T>, Sl
/**
* The cyclable objects handled by the scheduler.
*/
protected Set<T> cyclables = new LinkedHashSet<>();
protected List<T> cyclables = new ArrayList<>();
/**
* The cyclables that must be added in the next cycle.
......@@ -195,6 +193,8 @@ public class MonoThreadedCycling<T extends Cyclable> implements Scheduler<T>, Sl
*/
protected void treatPendingCyclables() {
cyclables.addAll(pendingToAddCyclables);
Collections.shuffle(cyclables);
pendingToAddCyclables.clear();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment