/* * @(#)Worker.java 1.10 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package com.sun.xlet.ixc; import java.rmi.RemoteException; /** * A Worker is an object that takes requests in one thread and executes * them in another. For correctness reasons, it's important that a Worker * appear to allocate a different thread for each request -- it must be * possible to have an unlimited number of concurrently executing requests. */ class Worker implements Runnable { // This implementation keeps one thread around at all times. If a call // comes in and this thread is busy, it creates a new thread just for // that second call. The expectation is that concurrently executing // calls are relatively rare, and that thread creation is relatively // expensive. private Thread thread = null; private Runnable work = null; private Object ticket = new Object(); // Null means thread is available private boolean destroyed = false; private String threadName; private int threadNo = 0; Worker(String threadName) { this.threadName = threadName; } synchronized void destroy() { destroyed = true; work = null; ticket = null; notifyAll(); } // // called by execcuteForClient() with the lock held // private void createThread() throws RemoteException { Object t = ticket; thread = new Thread(this, threadName); thread.start(); while (t == ticket) { try { wait(); } catch (InterruptedException ex) { throw new RemoteException("Thread interrupted", ex); } } } void execute(Runnable r) throws RemoteException { boolean busy; synchronized (this) { if (destroyed) { throw new RemoteException("Remote xlet has been killed"); } if (thread == null) { createThread(); } busy = ticket != null; if (!busy) { Object t = new Object(); ticket = t; work = r; notifyAll(); try { do { wait(); } while (t == ticket); } catch (InterruptedException ex) { throw new RemoteException("Worker thread interruped", ex); } } } if (busy) { Thread t = new Thread(r, threadName + " subthread " + (++threadNo)); t.start(); try { t.join(); } catch (InterruptedException ex) { throw new RemoteException("Worker thread interruped", ex); } } } // // The method that thread runs // public void run() { Runnable r = null; for (;;) { synchronized (this) { // assert (ticket != null) work = null; ticket = null; notifyAll(); do { if (destroyed) { return; } try { wait(); } catch (InterruptedException ex) {// assert(false) // If assertions are off, ignore. } r = work; } while (r == null); // assert ticket != null } try { r.run(); } catch (Throwable t) { t.printStackTrace(); // assert(false); } } } }