/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2009-2010, Martin Schoeberl (martin@jopdesign.com) 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, either version 3 of the License, or (at your option) any later version. 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, see <http://www.gnu.org/licenses/>. */ package jembench; /** * A minimal framework for work distribution to the CMP cores. * * @author Martin Schoeberl (martin@jopdesign.com) * */ public class ParallelExecutor { /** * A helper class that runs forever and executes work * if there is some more to do. * * @author martin * */ private class Worker extends Thread { volatile boolean finished; Runnable work; public Worker() { finished = true; } void setExecute(Runnable r) { work = r; } public void run() { for (;;) { if (!finished) { work.run(); finished = true; } else { if (requestStop) { // break out and terminate this thread break; } } } } } /** Executor not needed anymore - stop threads */ private volatile boolean requestStop; private Worker runner[]; int cpus = Util.getNrOfCores(); private ParallelExecutor() { runner = new Worker[cpus-1]; } private static ParallelExecutor pe; static ParallelExecutor getExecutor() { synchronized (ParallelExecutor.class) { if (pe==null) { pe = new ParallelExecutor(); } } return pe; } /** * Create and start all worker threads */ public void start() { requestStop = false; for (int i=0; i<cpus-1; i++) { runner[i] = new Worker(); runner[i].start(); } } /** * Request termination from the worker threads */ public void stop() { requestStop = true; // we could do some waiting for the terminating threads.... } /** * Does the parallel execution. Can reuse the worker threads * without stop/start. * @param r */ public void executeParallel(Runnable r) { // distribute the work to all cores. for (int i=0; i<cpus-1; ++i) { runner[i].setExecute(r); runner[i].finished = false; } // do also some work r.run(); // Now wait for others finishing their work. // We could use join, but the following is // also OK. boolean allFinished; do { allFinished = true; for (int i=0; i<cpus-1; ++i) { allFinished &= runner[i].finished; } } while (!allFinished); // now we can return } /** * Does the parallel execution. Can reuse the worker threads * without stop/start. * @param r */ public void executeParallel(Runnable r[]) { // distribute the work to all cores. for (int i=0; i<cpus-1; ++i) { runner[i].setExecute(r[i+1]); runner[i].finished = false; } // do also some work r[0].run(); // Now wait for others finishing their work. // We could use join, but the following is // also OK. boolean allFinished; do { allFinished = true; for (int i=0; i<cpus-1; ++i) { allFinished &= runner[i].finished; } } while (!allFinished); // now we can return } }