ohrstrom@1504: /* ohrstrom@1504: * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ohrstrom@1504: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohrstrom@1504: * ohrstrom@1504: * This code is free software; you can redistribute it and/or modify it ohrstrom@1504: * under the terms of the GNU General Public License version 2 only, as ohrstrom@1504: * published by the Free Software Foundation. Oracle designates this ohrstrom@1504: * particular file as subject to the "Classpath" exception as provided ohrstrom@1504: * by Oracle in the LICENSE file that accompanied this code. ohrstrom@1504: * ohrstrom@1504: * This code is distributed in the hope that it will be useful, but WITHOUT ohrstrom@1504: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohrstrom@1504: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohrstrom@1504: * version 2 for more details (a copy is included in the LICENSE file that ohrstrom@1504: * accompanied this code). ohrstrom@1504: * ohrstrom@1504: * You should have received a copy of the GNU General Public License version ohrstrom@1504: * 2 along with this work; if not, write to the Free Software Foundation, ohrstrom@1504: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohrstrom@1504: * ohrstrom@1504: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohrstrom@1504: * or visit www.oracle.com if you need additional information or have any ohrstrom@1504: * questions. ohrstrom@1504: */ ohrstrom@1504: ohrstrom@1504: package com.sun.tools.sjavac.server; ohrstrom@1504: ohrstrom@1504: import java.util.concurrent.ExecutorService; ohrstrom@1504: import java.util.concurrent.Executors; ohrstrom@1504: import java.util.concurrent.Semaphore; ohrstrom@1504: import java.util.Stack; ohrstrom@1504: import java.util.concurrent.Future; ohrstrom@1504: ohrstrom@1504: /** The compiler pool maintains compiler threads. ohrstrom@1504: * ohrstrom@1504: *

This is NOT part of any supported API. ohrstrom@1504: * If you write code that depends on this, you do so at your own ohrstrom@1504: * risk. This code and its internal interfaces are subject to change ohrstrom@1504: * or deletion without notice.

ohrstrom@1504: */ ohrstrom@1504: public class CompilerPool { ohrstrom@1504: // The javac server that created this pool. ohrstrom@1504: private JavacServer javacServer; ohrstrom@1504: // A semaphore protecting the poolsize number of threads. ohrstrom@1504: private Semaphore available; ohrstrom@1504: // The stack of compiler threads. ohrstrom@1504: private Stack compilers = new Stack(); ohrstrom@1504: // And the executor server to spawn threads. ohrstrom@1504: private final ExecutorService executorPool; ohrstrom@1504: // How many requests are active right now? ohrstrom@1504: private int concurrentRequests = 0; ohrstrom@1504: // When was the last request finished? ohrstrom@1504: private long lastRequestFinished = 0; ohrstrom@1504: // The total number of requests to this pool. ohrstrom@1504: private int numRequests = 0; ohrstrom@1504: // Protect access to the three above values. ohrstrom@1504: private static final Object conc = new Object(); ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Return the javac server that this pool belongs to. ohrstrom@1504: */ ohrstrom@1504: public JavacServer getJavacServer() { ohrstrom@1504: return javacServer; ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Return how many threads are running at this very moment. ohrstrom@1504: */ ohrstrom@1504: public int numActiveRequests() ohrstrom@1504: { ohrstrom@1504: synchronized (conc) { ohrstrom@1504: return concurrentRequests; ohrstrom@1504: } ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Return when the last request was finished. ohrstrom@1504: * I.e. the pool has been idle since. ohrstrom@1504: */ ohrstrom@1504: public long lastRequestFinished() ohrstrom@1504: { ohrstrom@1504: synchronized (conc) { ohrstrom@1504: return lastRequestFinished; ohrstrom@1504: } ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Up the number of active requests. ohrstrom@1504: */ ohrstrom@1504: public int startRequest() { ohrstrom@1504: int n; ohrstrom@1504: synchronized (conc) { ohrstrom@1504: concurrentRequests++; ohrstrom@1504: numRequests++; ohrstrom@1504: n = numRequests; ohrstrom@1504: } ohrstrom@1504: return n; ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Down the number of active requests. Return the current time. ohrstrom@1504: */ ohrstrom@1504: public long stopRequest() { ohrstrom@1504: synchronized (conc) { ohrstrom@1504: concurrentRequests--; ohrstrom@1504: lastRequestFinished = System.currentTimeMillis(); ohrstrom@1504: } ohrstrom@1504: return lastRequestFinished; ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Create a new compiler pool. ohrstrom@1504: */ ohrstrom@1504: CompilerPool(int poolsize, JavacServer server) { ohrstrom@1504: available = new Semaphore(poolsize, true); ohrstrom@1504: javacServer = server; ohrstrom@1504: executorPool = Executors.newFixedThreadPool(poolsize); ohrstrom@1504: lastRequestFinished = System.currentTimeMillis(); ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Execute a compiler thread. ohrstrom@1504: */ ohrstrom@1504: public void execute(CompilerThread ct) { ohrstrom@1504: executorPool.execute(ct); ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Execute a minor task, for example generating bytecodes and writing them to disk, ohrstrom@1504: * that belong to a major compiler thread task. ohrstrom@1504: */ ohrstrom@1504: public Future executeSubtask(CompilerThread t, Runnable r) { ohrstrom@1504: return executorPool.submit(r); ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Shutdown the pool. ohrstrom@1504: */ ohrstrom@1504: public void shutdown() { ohrstrom@1504: executorPool.shutdown(); ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Acquire a compiler thread from the pool, or block until a thread is available. ohrstrom@1504: * If the pools is empty, create a new thread, but never more than is "available". ohrstrom@1504: */ ohrstrom@1504: public CompilerThread grabCompilerThread() throws InterruptedException { ohrstrom@1504: available.acquire(); ohrstrom@1504: if (compilers.empty()) { ohrstrom@1504: return new CompilerThread(this); ohrstrom@1504: } ohrstrom@1504: return compilers.pop(); ohrstrom@1504: } ohrstrom@1504: ohrstrom@1504: /** ohrstrom@1504: * Return the specified compiler thread to the pool. ohrstrom@1504: */ ohrstrom@1504: public void returnCompilerThread(CompilerThread h) { ohrstrom@1504: compilers.push(h); ohrstrom@1504: available.release(); ohrstrom@1504: } ohrstrom@1504: } ohrstrom@1504: