/******************************************************** * Copyright (C) 2008 Course Scheduler Team * * This program is free software; you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to: * Free Software Foundation, Inc. * 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA ********************************************************/ /********************************************************* * Course Scheduler * File: ThreadSynch.java * * Contains class: * * ThreadSynch: * * Purpose: To synchronize the work of the worker threads * * @author Mike Reinhold *********************************************************/ package Scheduler; //declare as member of scheduler package /********************************************************* * The following imports are necessary for this class *********************************************************/ import java.util.ArrayList; //for storing lists import java.util.Vector; //for the worker thread list import javax.swing.SwingWorker; //the worker threads are SwingWorkers import javax.swing.ProgressMonitor; //for monitoring the progress /********************************************************* * Class ThreadSynch * * @purpose To help synchronize shared objects between threads *********************************************************/ public class ThreadSynch { /********************************************************* * The following are static constants for versioning *********************************************************/ protected static final long versionID = 2013010900015L; //object version /********************************************************* * The following are public static class fields *********************************************************/ public static int invalid = -1; //the invalid value /********************************************************* * The following are protected class fields *********************************************************/ protected int finished = 0; //the number of finished items protected boolean allowUpdate = true; //if monitor updates are allowed /********************************************************* * The following are private class fields *********************************************************/ private ProgressMonitor watch; //progress monitor for downloads private Vector<SwingWorker<Void,Void>> helpers;//rmp helper threads private Thread parent; //the parent thread private boolean isCancelled = false; //if the operation is cancelled private ArrayList<String> primary; //the primary course list private MakeSchedule owner; //the owning frame for this synchronization object protected boolean failed = false; //if the build failed, initialize to false private CourseType type; //the course types allowed private int permute; //the maximum value of the monitor private Vector<Conflict> conflicts; //the conflicts from this schedule build /********************************************************* * (Constructor) * * @purpose constructs a new ThreadSynch objet and initialized the * necessary fields *********************************************************/ public ThreadSynch(){ helpers = new Vector<SwingWorker<Void,Void>>(); conflicts = new Vector<Conflict>(); } /********************************************************* * @purpose adds a SwingWorker Helper to the helper list * * @param SwingWorker<Void,Void> helper: the worker to add * * @see synchronized *********************************************************/ public synchronized void addHelper(SwingWorker<Void,Void> helper){ helpers.add(helper); //add the worker } /********************************************************* * @purpose increment the progress and update the progress monitor * * @see synchronized *********************************************************/ public synchronized void incrementProgress(){ finished++; //increment the finished value updateWatch(null, finished); //only change the progress int } /********************************************************* * @purpose Closes the progress monitor for this sync object *********************************************************/ public void closeWatch(){ allowUpdate = false; //disallow updates watch.close(); //close the monitor } /********************************************************* * @purpose Synchronously update the progress monitor * * @param String note: the string to set as the monitor's note * @param int progress: the int value to use as the progress * * @see synchronized *********************************************************/ public synchronized void updateWatch(String note, int progress){ if(note != null){ //check if note is not null watch.setNote(note); //set the note if not null } if(progress != invalid){ //check if progress is not invalid watch.setProgress(progress); //set the progress if not invalid } } /********************************************************* * @purpose Returns if the operation is cancelled *********************************************************/ public synchronized boolean isCanceled(){ return isCancelled || watch.isCanceled();//return operation cancelled or monitor cancelled } /********************************************************* * @purpose Returns the progress monitor associated with this synch object * * @return ProgressMonitor: this synch objects monitor *********************************************************/ public ProgressMonitor getWatch() { return watch; //return the monitor } /********************************************************* * @purpose Sets the progress monitor for this synch object * * @param ProgressMonitor watch: the monitor for this thread *********************************************************/ public void setWatch(ProgressMonitor watch) { this.watch = watch; //set the monitor } /********************************************************* * @purpose Returnt the list of helper threads * * @return ArrayList<SwingWorker<Void,Void>>: the list of workers *********************************************************/ public Vector<SwingWorker<Void,Void>> getHelpers() { return helpers; //return the list of workers } /********************************************************* * @purpose set the list of helper workers * * @param ArrayList<SwingWorker<Void,Void>> helpers: the list of workers *********************************************************/ public void setHelpers(Vector<SwingWorker<Void,Void>> helpers) { this.helpers = helpers; //set the list of helper workers } /********************************************************* * @purpose return the parent thread * * @return Thread: the parent thread that this synch object is working for *********************************************************/ public Thread getParent() { return parent; //return the parent thread } /********************************************************* * @purpose Sets the parent thread for this synch object * * @param Thread parent: the thread that should be this objects parent *********************************************************/ public void setParent(Thread parent) { this.parent = parent; //set the parent thread } /********************************************************* * @purpose Cancels this synch objects operation *********************************************************/ public void cancel(){ isCancelled = true; //set cancelled allowUpdate = false; //disallow progress monitor updates for(SwingWorker<Void,Void> helper: helpers){//for each worker helper.cancel(true); //cancel the worker } } /********************************************************* * @purpose return if this synch object has living helpers * * @return boolean: if there are living worker threads *********************************************************/ public boolean hasLivingHelpers(){ return !helpers.isEmpty(); //return if any workers are living } /********************************************************* * @purpose Removes the helper from the list of helpers in a synchronized manner * * @param SwingWorker<Void,Void> helper: the worker to remove from the list of helpers *********************************************************/ public synchronized void removeHelper(SwingWorker<Void,Void> helper){ helpers.remove(helper); //remove the helper } public ArrayList<String> getPrimary() { return primary; } public void setPrimary(ArrayList<String> primary) { this.primary = primary; } public MakeSchedule getOwner() { return owner; } public void setOwner(MakeSchedule owner) { this.owner = owner; } public CourseType getType() { return type; } public void setType(CourseType type) { this.type = type; } /******************************************************** * @purpose Increment the progress displayed on the progress monitor * in a synchronized manner * * @see synchronized ********************************************************/ public synchronized void incrementProgressValue(){ finished++; //increment number of finished schedules } public synchronized void updateProgressValue(){ updateWatch("Finished " + //display the new progress finished + " of " + permute + ".", finished); } public int getPermute() { return permute; } public void setPermute(int permute) { watch.setMaximum(permute); this.permute = permute; } public Vector<Conflict> getConflicts() { return conflicts; } public void setConflicts(Vector<Conflict> conflicts) { this.conflicts = conflicts; } public void addConflict(Conflict toAdd){ conflicts.add(toAdd); } }