001: /*
002: * @(#)PXletStateQueue.java 1.6 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 sun.mtask.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 PXletStateQueue {
039: EventQueueItem head = null;
040: EventQueueItem tail = null;
041: PXletManager 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 PXletStateQueue(PXletManager 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: dispatchEvents();
057: }
058: }
059: }, "XletStateQueue lookup thread");
060: queueThread.start();
061: }
062:
063: // Push the request to the queue.
064: public synchronized void push(XletState desired) {
065: if (head == null) {
066: // empty queue
067: head = new EventQueueItem(desired);
068: tail = head;
069: } else {
070: tail.next = new EventQueueItem(desired);
071: tail = tail.next;
072: }
073: notifyAll();
074: }
075:
076: // Pop the request from the queue.
077: public synchronized XletState pop() {
078: XletState returningState = null;
079: if (head != null) {
080: returningState = head.state;
081: head = head.next;
082: }
083: return returningState;
084: }
085:
086: // True if there is no request pending in the queue.
087: public synchronized boolean isEmpty() {
088: return (head == null);
089: }
090:
091: // Clear up all the requests in this queue.
092: public synchronized void clear() {
093: head = tail = null;
094: }
095:
096: // Destroy the queue. Called when the xlet is destroyed.
097: public synchronized void destroy() {
098: clear();
099: isAlive = false;
100: notifyAll();
101: }
102:
103: private synchronized void waitForEvent() {
104: while (isEmpty() && isAlive) {
105: try {
106: wait();
107: } catch (InterruptedException e) {
108: }
109: }
110: }
111:
112: //
113: // Process the xlet state change request pending in this queue.
114: // Note that dispatchEvents() should NOT be synchronized
115: // since if handleRequest() blocks, new states cannot be queued
116: //
117: public void dispatchEvents() {
118: waitForEvent();
119: if (!isAlive)
120: return;
121: manager.handleRequest(pop());
122: }
123: }
124:
125: // Basic state change request date object kept in the queue.
126: class EventQueueItem {
127: XletState state;
128: EventQueueItem next;
129:
130: EventQueueItem(XletState state) {
131: this .state = state;
132: }
133: }
134:
135: // Extended state change request date object kept in the queue.
136: // This is to hide XletState objects that cannot be of a final state
137: // (INITIALIZE and CONDITIONAL_DESTROY are valid state change requests
138: // but not valid states for an xlet to be in.)
139: class DesiredXletState extends XletState {
140: static final XletState INITIALIZE;
141: static final XletState CONDITIONAL_DESTROY;
142: static {
143: INITIALIZE = new XletState("initialize");
144: CONDITIONAL_DESTROY = new XletState("conditional_destroy");
145: }
146:
147: protected DesiredXletState(String name) {
148: super (name);
149: }
150: }
151:
152: // XletState class object - to keep track of the current xlet state.
153: class XletState {
154: static final XletState UNLOADED;
155: static final XletState LOADED;
156: static final XletState PAUSED;
157: static final XletState ACTIVE;
158: static final XletState DESTROYED;
159: private String name = null;
160:
161: protected XletState(String name) {
162: this .name = name;
163: }
164:
165: public String toString() {
166: return name;
167: }
168:
169: static {
170: UNLOADED = new XletState("unloaded");
171: LOADED = new XletState("loaded");
172: PAUSED = new XletState("paused");
173: ACTIVE = new XletState("active");
174: DESTROYED = new XletState("destroyed");
175: }
176: }
|