diff --git a/src/example/philosophes/MainPhilosophe.java b/src/example/philosophes/MainPhilosophe.java index aaa05b05db64b3209a8eddedff27a6b3cb3793cd..03fed1cd55d6bbc8785599917601fae80c17c5da 100644 --- a/src/example/philosophes/MainPhilosophe.java +++ b/src/example/philosophes/MainPhilosophe.java @@ -1,15 +1,49 @@ package example.philosophes; +import mas.core.Cyclable; import mas.core.Schedulable; import mas.implementation.schedulers.FairCycling; +import java.util.ArrayList; +import java.util.List; + public class MainPhilosophe { public static void main(String[] args) { - final long startTime = System.nanoTime(); + class MyFairCycling extends FairCycling{ + + long startTimeCycle = 0; + + List<Long> cycleTime = new ArrayList<>(); + + public MyFairCycling(Cyclable... _cyclables){ + super(_cyclables); + + } - int nAgents = 6; + @Override + public boolean stopCondition() { + return nbOfCycles == 1000; + } + + @Override + protected void onCycleStarts() { + startTimeCycle = System.nanoTime(); + } + + @Override + protected void onCycleEnds() { + cycleTime.add(System.nanoTime() - startTimeCycle); + } + + public String getCycleTime(){ + double moyenne = cycleTime.stream().mapToLong(value -> value).average().orElse(0.0); + return "\tCycle moyen : " + moyenne + " nanoseconds"; + } + } + + int nAgents = 1000; Philosopher[] philosophers = new Philosopher[nAgents]; Fork[] forks = new Fork[nAgents]; @@ -27,11 +61,37 @@ public class MainPhilosophe { philosophers[i].setRightPhilosopher(philosophers[(i+1) % nAgents]); } - Schedulable scheduler = new FairCycling(philosophers); - scheduler.setSleep(100); + MyFairCycling scheduler = new MyFairCycling(philosophers); + scheduler.setSleep(0); + + final long startTimeSequential = System.nanoTime(); + + int nbCycle = 0; + long startTimeCycleSequential = 0; + List<Long> cycleTimeSequential = new ArrayList<>(); + + while(nbCycle < 1000){ + startTimeCycleSequential = System.nanoTime(); + + for(Philosopher philosopher : philosophers){ + philosopher.cycle(); + } + + cycleTimeSequential.add(System.nanoTime() - startTimeCycleSequential); + + nbCycle++; + } + + final long endTimeSequential = System.nanoTime(); + + System.out.println("Iterative : Total execution time: " + (endTimeSequential / 1000000 - startTimeSequential / 1000000) + " microseconds"); + System.out.println("\tCycle : " + cycleTimeSequential.stream().mapToLong(value -> value).average().orElse(0.0) + " nanoseconds"); + + final long startTime = System.nanoTime(); + scheduler.start(); - try { + /*try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); @@ -53,12 +113,13 @@ public class MainPhilosophe { throw new RuntimeException(e); } - scheduler.stop(); + scheduler.stop();*/ scheduler.waitUntilFinish(); final long endTime = System.nanoTime(); - System.out.println("Total execution time: " + (endTime / 1000000 - startTime / 1000000) + " microseconds"); + System.out.println("AMAk : Total execution time: " + (endTime / 1000000 - startTime / 1000000) + " microseconds"); + System.out.println(scheduler.getCycleTime()); } } diff --git a/src/example/philosophes/Philosopher.java b/src/example/philosophes/Philosopher.java index 5ae3fb23f93e7c93504203c195e44e8a430f312a..f9131a394714a7df9fd8df1f86c916ba2a706188 100644 --- a/src/example/philosophes/Philosopher.java +++ b/src/example/philosophes/Philosopher.java @@ -119,7 +119,7 @@ public class Philosopher extends Agent { @Override public void act() { //System.out.println("Philosopher num " + id + " act"); - scheduler.addCyclable(new Waste(id)); + //scheduler.addCyclable(new Waste(id)); } @Override diff --git a/src/mas/core/Agent.java b/src/mas/core/Agent.java index eb85fde476e067e1f15ee042bafd3500a3efaaa9..3980769f8388ac557552f4ab20652b4e14d201e1 100644 --- a/src/mas/core/Agent.java +++ b/src/mas/core/Agent.java @@ -2,6 +2,9 @@ package mas.core; public class Agent implements ThreeStepCyclable{ + /** + * The scheduler of the agent. + */ protected Schedulable scheduler; @Override diff --git a/src/mas/core/Cyclable.java b/src/mas/core/Cyclable.java index 05a7fde131c41402cd9f5e804ebadbca4863f54d..ac6ed97d60eb60fd388c40f9dec062246a79b132 100644 --- a/src/mas/core/Cyclable.java +++ b/src/mas/core/Cyclable.java @@ -1,23 +1,24 @@ package mas.core; /** - * A cyclable objet + * A cyclable objet. */ public interface Cyclable { /** - * TODO + * This method represents the agent's cycle. */ void cycle(); /** - * TODO - * @return + * Condition to stop the execution of an agent at the end of the next cycle. + * + * @return true if the cyclable should finish its execution, false otherwise. */ boolean terminate(); /** - * TODO + * Set the scheduler in which the cyclable is going to be scheduled. */ void setScheduler(Schedulable _scheduler); } diff --git a/src/mas/core/Schedulable.java b/src/mas/core/Schedulable.java index f09083297627b1a040ec1b018a70d745a29492ee..3712675e11dab9a276117b75087e22db4f9ed4f7 100644 --- a/src/mas/core/Schedulable.java +++ b/src/mas/core/Schedulable.java @@ -1,7 +1,7 @@ package mas.core; /** - * A schedulable object can be controlled by a scheduler + * A schedulable object can be controlled by a scheduler. * */ public interface Schedulable { @@ -9,55 +9,49 @@ public interface Schedulable { public static final int DEFAULT_SLEEP = 0; /** - * Launch the scheduler if it is not running + * Launch the scheduler if it is not running. */ void start(); /** - * Stops the scheduler if it is running + * Stops the scheduler if it is running. */ void stop(); /** - * Pause the scheduler at the end of the current cycle + * Pause the scheduler at the end of the current cycle. */ void pause(); /** - * Resumes the scheduler in his current state + * Resumes the scheduler in his current state. */ void resume(); /** - * TODO - */ - int getSleep(); - - /** - * TODO - * @param sleep - */ - void setSleep(int sleep); - - /** - * + * Add a Cyclable object to the scheduler and starts their cycle as soon as possible. */ void addCyclable(Cyclable cyclable); /** - * TODO - * @return + * This method allows the scheduler to stop on certain conditions. + * + * @return whether or not the scheduler must stop. */ boolean stopCondition(); /** - * TODO + * Shows if the scheduler as been stopped. + * + * @return if the scheduler as been stopped. */ boolean isFinished(); /** - * TODO + * Pause the execution until the executor has finished. + * + * This function needs to be called after a call to {@link Schedulable#stop()} or with the redefinition of {@link Schedulable#stopCondition()}. */ void waitUntilFinish(); } diff --git a/src/mas/core/ThreeStepCyclable.java b/src/mas/core/ThreeStepCyclable.java index 8a9d0b586aec5d5dc8162921a390fc7f5d322392..e2be1db5f83f15b087776176caa5b970f28b0525 100644 --- a/src/mas/core/ThreeStepCyclable.java +++ b/src/mas/core/ThreeStepCyclable.java @@ -1,7 +1,7 @@ package mas.core; /** - * TODO + * The ThreeStepCyclable interface should be implemented by any agent whose cycle is defined in three steeps (perceive, decide and act). */ public interface ThreeStepCyclable extends Cyclable { @@ -13,17 +13,17 @@ public interface ThreeStepCyclable extends Cyclable { }; /** - * TODO + * This method represents the perception phase of the agent. */ void perceive(); /** - * TODO + * This method represents the decision phase of the agent. */ void decide(); /** - * TODO + * This method represents the phase in which the agent performs its action. */ void act(); } diff --git a/src/mas/core/TwoStepCyclable.java b/src/mas/core/TwoStepCyclable.java index 398864e43d4c74dbafe6bc651401216fc340bf4f..dc6a1daeb326cec60a22a190b3cc9a5ddaf05792 100644 --- a/src/mas/core/TwoStepCyclable.java +++ b/src/mas/core/TwoStepCyclable.java @@ -1,5 +1,8 @@ package mas.core; +/** + * The TwoStepCyclable interface should be implemented by any agent whose cycle is defined in two steeps (perceive and decideAndAct). + */ public interface TwoStepCyclable extends Cyclable { @Override @@ -9,12 +12,12 @@ public interface TwoStepCyclable extends Cyclable { }; /** - * TODO + * This method represents the perception phase of the agent. */ void perceive(); /** - * TODO + * This method represents the decideAndAct phase of the agent. */ void decideAndAct(); } diff --git a/src/mas/environment/TwoDContinuosGrid.java b/src/mas/environment/TwoDContinuosGrid.java index 5cc7896232d1b82233c79930fd9f49c1bf6bb431..13f164513fb38c8f7a1fbfc08ea9a736d6ccfa1e 100644 --- a/src/mas/environment/TwoDContinuosGrid.java +++ b/src/mas/environment/TwoDContinuosGrid.java @@ -1,5 +1,8 @@ package mas.environment; +/** + * TODO + */ public class TwoDContinuosGrid { private int width; diff --git a/src/mas/implementation/schedulers/AsyncCycling.java b/src/mas/implementation/schedulers/AsyncCycling.java index 1e09c47fea3b70e588dfb5e0884238ae6d56397e..fd3f15ba97d99e806df9ee214aabd6f803f8191f 100644 --- a/src/mas/implementation/schedulers/AsyncCycling.java +++ b/src/mas/implementation/schedulers/AsyncCycling.java @@ -8,17 +8,38 @@ import java.util.Set; import java.util.concurrent.*; /** - * Zero administration + * The AsyncCycling scheduler schedules tasks asynchronously using a {@link java.util.concurrent.ThreadPoolExecutor}. + * + * @author David Antunes */ public class AsyncCycling implements Schedulable { - private final Set<Cyclable> cyclables = new LinkedHashSet<>(); + /** + * The cyclable objects handled by the scheduler. + */ + protected final Set<Cyclable> cyclables = new LinkedHashSet<>(); + /** + * Time between two cycles. Default time in {@link Schedulable#DEFAULT_SLEEP}. + */ private int sleep = DEFAULT_SLEEP; - boolean mustStop = false; + /** + * Condition to know if the scheduler must be stopped. + */ + protected boolean mustStop = false; + + /** + * The executor of the tasks. + */ protected PausableThreadPoolExecutor executor = new PausableThreadPoolExecutor(); + /** + * Constructor which set the initial cyclables. + * + * @param _cyclables + * The corresponding cyclables + */ public AsyncCycling(Cyclable... _cyclables){ for(Cyclable cyclable : _cyclables){ @@ -88,16 +109,31 @@ public class AsyncCycling implements Schedulable { } } - @Override + /** + * Getter for the sleep time. + * + * @return the current time elapsed between each cyclable's cycle + */ public int getSleep() { return sleep; } - @Override + /** + * Setter for the sleep time. + * + * @param sleep + * The time between each cyclable's cycle + */ public void setSleep(int sleep) { this.sleep = sleep; } + /** + * Executes a cycle and set up the next cycle if needed. + * + * @param cyclable + * The cyclable + */ protected void manageCyclable(Cyclable cyclable){ cyclable.cycle(); @@ -110,6 +146,9 @@ public class AsyncCycling implements Schedulable { } } + /** + * Performs the waiting time between two cycles. + */ protected void doSleep(){ try { Thread.sleep(sleep); diff --git a/src/mas/implementation/schedulers/FairCycling.java b/src/mas/implementation/schedulers/FairCycling.java index 429e191c34e2638e96c311915c61e4fe9621db8e..79d4ae53ace5fae82f9734796abe9ed7c0dd67a0 100644 --- a/src/mas/implementation/schedulers/FairCycling.java +++ b/src/mas/implementation/schedulers/FairCycling.java @@ -7,26 +7,69 @@ import java.util.*; import java.util.concurrent.*; /** - * Chaque agent execute exactement 1 cycle pour chaque cycle systeme + * + * Chaque agent execute exactement 1 cycle pour chaque cycle systeme. + */ + +/** + * The FairCycling scheduler schedules tasks using a {@link Executors#newCachedThreadPool()}. + * Every cyclable executes its cycle once every system's cycle. + * + * @author David Antunes */ public class FairCycling implements Schedulable { + /** + * The cyclable objects handled by the scheduler. + */ protected Set<Cyclable> cyclables = new LinkedHashSet<>(); + + /** + * The cyclables that must be added in the next cycle. + */ protected Queue<Cyclable> pendingToAddCyclables = new ConcurrentLinkedQueue<>(); + /** + * Time between two cycles. Default time in {@link Schedulable#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; + /** + * The executor of the tasks. + */ protected ExecutorService executor = Executors.newCachedThreadPool(); + /** + * Object used to pause the scheduler. + */ protected CountDownLatch pauseLatch; + + /** + * Object that synchronize each cyclable every system's cycle. + */ protected CountDownLatch cycleLatch; + /** + * Constructor which set the initial cyclables. + * + * @param _cyclables + * The corresponding cyclables + */ public FairCycling(Cyclable... _cyclables) { for (Cyclable cyclable : _cyclables) { @@ -77,28 +120,50 @@ public class FairCycling implements Schedulable { } } + /** + * 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(){ + + } + @Override public void addCyclable(Cyclable cyclable){ cyclable.setScheduler(this); pendingToAddCyclables.add(cyclable); } - @Override + /** + * Getter for the sleep time. + * + * @return the current time elapsed between each system's cycle + */ public int getSleep() { return sleep; } - @Override + /** + * Setter for the sleep time. + * + * @param sleep + * The time between each system's cycle + */ public void setSleep(int sleep) { this.sleep = sleep; } + /** + * Executes a system's cycle + */ protected void step() { - nbOfCycles++; + onCycleStarts(); treatPendingCyclables(); @@ -126,8 +191,13 @@ public class FairCycling implements Schedulable { cyclables.clear(); onCycleEnds(); + + nbOfCycles++; } + /** + * Executes a {@link #step()} and set up the next step if needed. + */ protected void doCycle() { step(); if(stopCondition()){ @@ -146,22 +216,33 @@ public class FairCycling implements Schedulable { } } + /** + * Add the cyclables that are going to be scheduled on the current cycle. + */ protected void treatPendingCyclables() { Queue<Cyclable> buffer = new ConcurrentLinkedQueue<>(pendingToAddCyclables); cyclables.addAll(buffer); pendingToAddCyclables.clear(); } + /** + * Performs the waiting time between two cycles of the system. + */ protected void doSleep(){ if (getSleep() != 0) { try { - Thread.sleep(getSleep()); + Thread.sleep(sleep); } catch (final InterruptedException e) { e.printStackTrace(); } } } + /** + * Getter for the number of cycles. + * + * @return the number of cycles performed by the system + */ public int getNbOfCycles() { return nbOfCycles; } diff --git a/src/mas/implementation/schedulers/FairPosCycling.java b/src/mas/implementation/schedulers/FairPosCycling.java index 7881682bb5d64394d5ec25ba0f2b05f4444f8e2c..44bb30597c668a82b8f84ae890f584ef7cc1b652 100644 --- a/src/mas/implementation/schedulers/FairPosCycling.java +++ b/src/mas/implementation/schedulers/FairPosCycling.java @@ -27,12 +27,12 @@ public class FairPosCycling implements Schedulable { } - @Override + public int getSleep() { return 0; } - @Override + public void setSleep(int sleep) { }