001: /*
002: * @(#)XletStateQueue.java 1.9 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;
029:
030: /*
031: * Implements a queue that keeps track of incoming xlet state change requests
032: * and executes them in order. There is one queue per one xlet.
033: * By having this class, the caller requesting the xlet state change
034: * does not have to be blocked waiting for a lock even if another xlet state change
035: * request is being processed.
036: */
037:
038: public class XletStateQueue {
039: EventQueueItem head = null;
040: EventQueueItem tail = null;
041: XletManager manager;
042:
043: // The thread that's processing the requests. It should be in the
044: // ThreadGroup created by the XletManager.
045: Thread queueThread;
046:
047: // To check if the xlet is still alive (not destroyed).
048: boolean isAlive = true;
049:
050: public XletStateQueue(XletManager xletManager) {
051: this .manager = xletManager;
052: queueThread = new Thread(manager.threadGroup, new Runnable() {
053: public void run() {
054: while (isAlive
055: && manager.getXletState() != XletState.DESTROYED) {
056: dispatchRequests();
057: }
058: }
059: }, "XletStateQueue lookup thread");
060: queueThread.setContextClassLoader(xletManager.getClassLoader());
061: queueThread.start();
062: }
063:
064: // Push the request to the queue.
065: public synchronized void push(XletState desired) {
066: if (head == null) {
067: // empty queue
068: head = new EventQueueItem(desired);
069: tail = head;
070: } else {
071: tail.next = new EventQueueItem(desired);
072: tail = tail.next;
073: }
074: notifyAll();
075: }
076:
077: // Pop the request from the queue.
078: public synchronized XletState pop() {
079: XletState returningState = null;
080: if (head != null) {
081: returningState = head.state;
082: head = head.next;
083: }
084: return returningState;
085: }
086:
087: // True if there is no request pending in the queue.
088: public synchronized boolean isEmpty() {
089: return (head == null);
090: }
091:
092: // Clear up all the requests in this queue.
093: public synchronized void clear() {
094: head = tail = null;
095: }
096:
097: // Destroy the queue. Called when the xlet is destroyed.
098: public synchronized void destroy() {
099: clear();
100: isAlive = false;
101: notifyAll();
102: }
103:
104: // Process the xlet state change request pending in this queue.
105: public synchronized void dispatchRequests() {
106: while (isEmpty() && isAlive) {
107: try {
108: wait();
109: } catch (InterruptedException e) {
110: }
111: }
112: if (!isAlive)
113: return;
114: manager.handleRequest(pop());
115: }
116: }
117:
118: // Basic state change request date object kept in the queue.
119: class EventQueueItem {
120: XletState state;
121: EventQueueItem next;
122:
123: EventQueueItem(XletState state) {
124: this .state = state;
125: }
126: }
127:
128: // Extended state change request date object kept in the queue.
129: // This is to hide XletState objects that cannot be of a final state
130: // (INITIALIZE and CONDITIONAL_DESTROY are valid state change requests
131: // but not valid states for an xlet to be in.)
132: class DesiredXletState extends XletState {
133: static final XletState INITIALIZE;
134: static final XletState CONDITIONAL_DESTROY;
135: static {
136: INITIALIZE = new XletState("initialize");
137: CONDITIONAL_DESTROY = new XletState("conditional_destroy");
138: }
139:
140: protected DesiredXletState(String name) {
141: super (name);
142: }
143: }
144:
145: // XletState class object - to keep track of the current xlet state.
146: class XletState {
147: static final XletState UNLOADED;
148: static final XletState LOADED;
149: static final XletState PAUSED;
150: static final XletState ACTIVE;
151: static final XletState DESTROYED;
152: private String name = null;
153:
154: protected XletState(String name) {
155: this .name = name;
156: }
157:
158: public String toString() {
159: return name;
160: }
161:
162: static {
163: UNLOADED = new XletState("unloaded");
164: LOADED = new XletState("loaded");
165: PAUSED = new XletState("paused");
166: ACTIVE = new XletState("active");
167: DESTROYED = new XletState("destroyed");
168: }
169: }
|