001: /*
002: * @(#)Worker.java 1.10 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package com.sun.xlet.ixc;
029:
030: import java.rmi.RemoteException;
031:
032: /**
033: * A Worker is an object that takes requests in one thread and executes
034: * them in another. For correctness reasons, it's important that a Worker
035: * appear to allocate a different thread for each request -- it must be
036: * possible to have an unlimited number of concurrently executing requests.
037: */
038:
039: class Worker implements Runnable {
040: // This implementation keeps one thread around at all times. If a call
041: // comes in and this thread is busy, it creates a new thread just for
042: // that second call. The expectation is that concurrently executing
043: // calls are relatively rare, and that thread creation is relatively
044: // expensive.
045:
046: private Thread thread = null;
047: private Runnable work = null;
048: private Object ticket = new Object(); // Null means thread is available
049: private boolean destroyed = false;
050: private String threadName;
051: private int threadNo = 0;
052:
053: Worker(String threadName) {
054: this .threadName = threadName;
055: }
056:
057: synchronized void destroy() {
058: destroyed = true;
059: work = null;
060: ticket = null;
061: notifyAll();
062: }
063:
064: //
065: // called by execcuteForClient() with the lock held
066: //
067: private void createThread() throws RemoteException {
068: Object t = ticket;
069: thread = new Thread(this , threadName);
070: thread.start();
071: while (t == ticket) {
072: try {
073: wait();
074: } catch (InterruptedException ex) {
075: throw new RemoteException("Thread interrupted", ex);
076: }
077: }
078: }
079:
080: void execute(Runnable r) throws RemoteException {
081: boolean busy;
082: synchronized (this ) {
083: if (destroyed) {
084: throw new RemoteException("Remote xlet has been killed");
085: }
086: if (thread == null) {
087: createThread();
088: }
089: busy = ticket != null;
090: if (!busy) {
091: Object t = new Object();
092: ticket = t;
093: work = r;
094: notifyAll();
095: try {
096: do {
097: wait();
098: } while (t == ticket);
099: } catch (InterruptedException ex) {
100: throw new RemoteException(
101: "Worker thread interruped", ex);
102: }
103: }
104: }
105: if (busy) {
106: Thread t = new Thread(r, threadName + " subthread "
107: + (++threadNo));
108: t.start();
109: try {
110: t.join();
111: } catch (InterruptedException ex) {
112: throw new RemoteException("Worker thread interruped",
113: ex);
114: }
115: }
116: }
117:
118: //
119: // The method that thread runs
120: //
121: public void run() {
122: Runnable r = null;
123: for (;;) {
124: synchronized (this ) {
125: // assert (ticket != null)
126: work = null;
127: ticket = null;
128: notifyAll();
129: do {
130: if (destroyed) {
131: return;
132: }
133: try {
134: wait();
135: } catch (InterruptedException ex) {// assert(false)
136: // If assertions are off, ignore.
137: }
138: r = work;
139: } while (r == null);
140: // assert ticket != null
141: }
142: try {
143: r.run();
144: } catch (Throwable t) {
145: t.printStackTrace();
146: // assert(false);
147: }
148: }
149: }
150: }
|