BaseViewPaint.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.traceviewer.painter;
00002 
00003 import java.io.IOException;
00004 import java.util.ArrayList;
00005 import java.util.List;
00006 import java.util.concurrent.ExecutionException;
00007 import java.util.concurrent.ExecutorCompletionService;
00008 import java.util.concurrent.ExecutorService;
00009 import java.util.concurrent.Future;
00010 import java.util.Queue;
00011 import java.util.LinkedList;
00012 import java.util.concurrent.ConcurrentLinkedQueue;
00013 import java.util.concurrent.atomic.AtomicInteger;
00014 
00015 import org.eclipse.core.runtime.IProgressMonitor;
00016 import org.eclipse.core.runtime.IStatus;
00017 import org.eclipse.core.runtime.Status;
00018 import org.eclipse.jface.dialogs.MessageDialog;
00019 import org.eclipse.swt.custom.BusyIndicator;
00020 import org.eclipse.swt.graphics.Device;
00021 import org.eclipse.swt.widgets.Display;
00022 import org.eclipse.ui.IWorkbenchWindow;
00023 import org.eclipse.ui.progress.UIJob;
00024 
00025 import edu.rice.cs.hpc.common.ui.Util;
00026 import edu.rice.cs.hpc.data.util.OSValidator;
00027 
00028 import edu.rice.cs.hpc.traceviewer.spaceTimeData.SpaceTimeDataController;
00029 import edu.rice.cs.hpc.traceviewer.timeline.BaseTimelineThread;
00030 import edu.rice.cs.hpc.traceviewer.data.db.TimelineDataSet;
00031 import edu.rice.cs.hpc.traceviewer.data.util.Debugger;
00032 import edu.rice.cs.hpc.traceviewer.util.Utility;
00033 
00034 
00035 /******************************************************
00036  * 
00037  * Abstract class to paint depth view and detail view
00038  * The instance of the children of the class needs to 
00039  * implement the start and the end method of the painting
00040  * 
00041  *
00042  *******************************************************/
00043 public abstract class BaseViewPaint extends UIJob
00044 {
00045 
00046     protected ImageTraceAttributes attributes;
00047     protected boolean changedBounds;
00048     
00049     protected final IWorkbenchWindow window;
00050     
00051     protected SpaceTimeDataController controller;
00052 
00053     final private ExecutorService threadExecutor;
00054     final private ISpaceTimeCanvas canvas;
00055 
00067     public BaseViewPaint(String title, SpaceTimeDataController _data, ImageTraceAttributes _attributes, boolean _changeBound, 
00068             IWorkbenchWindow window, ISpaceTimeCanvas canvas, ExecutorService threadExecutor) 
00069     {
00070         super(title);
00071         
00072         changedBounds = _changeBound;
00073         controller = _data;
00074         attributes = _data.getAttributes();
00075 
00076         this.window         = (window == null ? Util.getActiveWindow() : window);
00077         this.canvas         = canvas;
00078         this.threadExecutor = threadExecutor;
00079     }
00080     
00081 
00082     @Override
00083     public IStatus runInUIThread(IProgressMonitor monitor) {
00084         IStatus status = Status.OK_STATUS;
00085         
00086         BusyIndicator.showWhile(getDisplay(), getThread());
00087         if (!paint(canvas, monitor))
00088         {
00089             status = Status.CANCEL_STATUS;
00090         }
00091         
00092         return status;
00093     }   
00094 
00095     /**********************************************************************************
00096      *  Paints the specified time units and processes at the specified depth
00097      *  on the SpaceTimeCanvas using the SpaceTimeSamplePainter given. Also paints
00098      *  the sample's max depth before becoming overDepth on samples that have gone over depth.
00099      *
00100      *  @param canvas            The SpaceTimeDetailCanvas that will be painted on.
00101      *  @return boolean true of the pain is successful, false otherwise
00102      ***********************************************************************************/
00103     public boolean paint(ISpaceTimeCanvas canvas, IProgressMonitor monitor)
00104     {   
00105         // depending upon how zoomed out you are, the iteration you will be
00106         // making will be either the number of pixels or the processors
00107         int linesToPaint = getNumberOfLines();
00108         Debugger.printDebug(2, "BVP-begin " + linesToPaint + " lines");
00109 
00110         // -------------------------------------------------------------------
00111         // hack fix: if the number of horizontal pixels is less than 1 we
00112         // return immediately, otherwise it throws an exception
00113         // -------------------------------------------------------------------
00114         if (attributes.numPixelsH <= 0)
00115             return false;
00116         
00117         // -------------------------------------------------------------------
00118         // initialize the painting (to be implemented by the instance
00119         // -------------------------------------------------------------------
00120         int launch_threads = Utility.getNumThreads(linesToPaint);
00121         if (!startPainting(linesToPaint, launch_threads, changedBounds))
00122             return false;
00123 
00124         monitor.beginTask(getName(), linesToPaint);
00125 
00126         // -------------------------------------------------------------------
00127         // Create multiple threads to collect data
00128         // -------------------------------------------------------------------
00129         
00130         // decompression can be done with multiple threads without accessing gtk (on linux)
00131         // It looks like there's no major performance effect though
00132         Debugger.printDebug(2, "BVP launch threads " + launch_threads);
00133         try {
00134             launchDataGettingThreads(changedBounds, launch_threads);
00135             
00136         } catch (Exception e) {
00137             MessageDialog.openError(window.getShell(), "Error while reading data", 
00138                     e.getMessage());
00139             e.printStackTrace();
00140             
00141             // shutdown the monitor to end the progress bar
00142             monitor.done();
00143             return false;
00144         }
00145         
00146         // -------------------------------------------------------------------
00147         // instantiate queue based on whether we need multi-threading or not
00148         // in case of multithreading, we want a thread-safe queue
00149         // -------------------------------------------------------------------
00150         final Queue<TimelineDataSet> queue;
00151         if (launch_threads > 1) {
00152             queue = new ConcurrentLinkedQueue<TimelineDataSet>();
00153         } else {
00154             queue = new LinkedList<TimelineDataSet>();
00155         }
00156 
00157         // -------------------------------------------------------------------
00158         // case where everything works fine, and all the data has been read,
00159         //  we paint the canvas using multiple threads
00160         // -------------------------------------------------------------------
00161         
00162         Debugger.printTimestampDebug("Rendering beginning (" + canvas.toString()+")");
00163 
00164         // reset the line number to paint
00165         controller.resetCounters();
00166         
00167         //final List<Future<Integer>> threads = new ArrayList<Future<Integer>>();
00168         final AtomicInteger timelineDone = new AtomicInteger(linesToPaint);
00169 
00170         final double xscale = canvas.getScalePixelsPerTime();
00171         final double yscale = Math.max(canvas.getScalePixelsPerRank(), 1);
00172         
00173         ExecutorCompletionService<Integer> ecs = new ExecutorCompletionService<>(threadExecutor);
00174         
00175         for (int threadNum = 0; threadNum < launch_threads; threadNum++) {
00176             final BaseTimelineThread thread = getTimelineThread(canvas, xscale, yscale, queue, 
00177                     timelineDone, monitor);
00178             ecs.submit(thread);
00179 /*          final Future<Integer> submit = threadExecutor.submit( thread );
00180             threads.add(submit);*/
00181         }
00182         
00183         // -------------------------------------------------------------------
00184         // draw to the canvas
00185         // -------------------------------------------------------------------
00186 
00187         // -------------------------------------------------------------------
00188         // hack: On Linux, gtk is not threads-safe, and SWT-gtk implementation
00189         //       uses lock everytime it calls gtk functions. This greatly impact
00190         //       performance degradation, and we don't have the solution until now.
00191         //  At the moment we don't see any reason to use multi-threading to render
00192         //       the canvas
00193         // -------------------------------------------------------------------
00194 
00195         Debugger.printDebug(1, canvas.toString() + " BVP --- lp: " + linesToPaint + ", tld: " + timelineDone + ", qs: " + queue.size());
00196         Debugger.printTimestampDebug("Rendering mostly finished. (" + canvas.toString()+")");
00197 
00198         if (OSValidator.isUnix()) 
00199         {
00200             // -------------------------------------------------------------------
00201             // sequential painting for Unix/Linux platform
00202             // -------------------------------------------------------------------
00203             final BasePaintThread thread = getPaintThread(queue, linesToPaint, timelineDone,
00204                     Display.getCurrent(), attributes.numPixelsH);
00205             ArrayList<Integer> result = new ArrayList<Integer>();
00206             waitDataPreparationThreads(ecs, result, 1);
00207             doSingleThreadPainting(canvas, thread);
00208         } else
00209         {
00210             // -------------------------------------------------------------------
00211             // painting to the buffer "concurrently" if numPaintThreads > 1
00212             // -------------------------------------------------------------------
00213             final List<Future<List<ImagePosition>>> threadsPaint = new ArrayList<Future<List<ImagePosition>>>();
00214 
00215             for (int threadNum=0; threadNum < launch_threads; threadNum++) 
00216             {
00217                 final BasePaintThread thread = getPaintThread(queue, linesToPaint, timelineDone,
00218                         Display.getCurrent(), attributes.numPixelsH);
00219                 if (thread != null) {
00220                     final Future<List<ImagePosition>> submit = threadExecutor.submit( thread );
00221                     threadsPaint.add(submit);
00222                 }
00223             }
00224             // -------------------------------------------------------------------
00225             // Finalize the painting (to be implemented by the instance)
00226             // -------------------------------------------------------------------
00227             ArrayList<Integer> result = new ArrayList<Integer>();
00228             waitDataPreparationThreads(ecs, result, launch_threads);
00229             endPainting(canvas, threadsPaint);
00230         }       
00231         Debugger.printTimestampDebug("Rendering finished. (" + canvas.toString()+")");
00232         monitor.done();
00233         changedBounds = false;
00234 
00235         return true;
00236     }
00237     
00238     /****
00239      * perform a data painting with only a single thread.
00240      * this method doesn't need collection or painting finalization since only one
00241      * thread is involved.
00242      * 
00243      * @param canvas
00244      * @param paintThread
00245      */
00246     private void doSingleThreadPainting(ISpaceTimeCanvas canvas, BasePaintThread paintThread)
00247     {
00248         try {
00249             // do the data painting, and directly get the generated images
00250             List<ImagePosition> listImages = paintThread.call();
00251 
00252             // set the images into the canvas. 
00253             for ( ImagePosition image: listImages )
00254             {
00255                 drawPainting(canvas, image);
00256             }
00257         } catch (Exception e) {
00258             e.printStackTrace();
00259         }
00260     }
00261     
00262     private void waitDataPreparationThreads(ExecutorCompletionService<Integer> ecs, 
00263             ArrayList<Integer> result, int launch_threads)
00264     {
00265         for (int i=0; i<launch_threads; i++)
00266         {
00267             try {
00268                 Integer linenum = ecs.take().get();
00269                 result.add(linenum);
00270             } catch (Exception e) {
00271                 e.printStackTrace();
00272             }
00273         }
00274     }
00275 
00276     /******
00277      * finalize the data collection, and put all images into a canvas
00278      * 
00279      * @param canvas
00280      * @param listOfImageThreads
00281      */
00282     private void endPainting(ISpaceTimeCanvas canvas, List<Future<List<ImagePosition>>> listOfImageThreads)
00283     {
00284         for( Future<List<ImagePosition>> listFutures : listOfImageThreads ) 
00285         {
00286             try {
00287                 List<ImagePosition> listImages = listFutures.get();
00288                 for (ImagePosition image : listImages) 
00289                 {
00290                     drawPainting(canvas, image);
00291                 }
00292                 
00293             } catch (InterruptedException e) {
00294                 // TODO Auto-generated catch block
00295                 e.printStackTrace();
00296             } catch (ExecutionException e) {
00297                 // TODO Auto-generated catch block
00298                 e.printStackTrace();
00299             }
00300         }
00301     }
00302     
00303     
00304     //------------------------------------------------------------------------------------------------
00305     // abstract methods 
00306     //------------------------------------------------------------------------------------------------
00307     
00316     abstract protected boolean startPainting(int linesToPaint, int numThreads, boolean changedBounds);
00317     
00318     /***
00319      * start painting an image to the canvas
00320      * 
00321      * @param canvas: canvas to be painted
00322      * @param imagePosition : a pair of image and position
00323      */
00324     abstract protected void drawPainting(ISpaceTimeCanvas canvas, ImagePosition imagePosition);
00325     
00330     abstract protected int getNumberOfLines();
00331     
00332     /****
00333      * launching threads for remote communication
00334      * 
00335      * @param changedBounds
00336      * @param numThreads
00337      * @throws IOException
00338      */
00339     abstract protected void launchDataGettingThreads(boolean changedBounds, int numThreads) 
00340             throws IOException;
00341 
00342     /****
00343      * get a thread for collecting timeline data
00344      * @param canvas
00345      * @param xscale
00346      * @param yscale
00347      * @param queue
00348      * @param timelineDone
00349      * @return
00350      */
00351     abstract protected BaseTimelineThread  getTimelineThread(ISpaceTimeCanvas canvas, double xscale, double yscale,
00352             Queue<TimelineDataSet> queue, AtomicInteger timelineDone, IProgressMonitor monitor);
00353     
00354     /***
00355      * get a thread for painting a number of lines
00356      * @param queue
00357      * @param numLines
00358      * @param timelineDone
00359      * @param device
00360      * @param width
00361      * @return
00362      */
00363     abstract protected BasePaintThread getPaintThread( Queue<TimelineDataSet> queue, int numLines, 
00364             AtomicInteger timelineDone, Device device, int width);
00365 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1