001: /*
002: * @(#)ScreenUpdater.java 1.30 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.awt;
029:
030: class ScreenUpdaterEntry {
031: UpdateClient client;
032: long when;
033: ScreenUpdaterEntry next;
034: Object arg;
035:
036: ScreenUpdaterEntry(UpdateClient client, long when, Object arg,
037: ScreenUpdaterEntry next) {
038: this .client = client;
039: this .when = when;
040: this .arg = arg;
041: this .next = next;
042: }
043: }
044:
045: /**
046: * A seperate low priority thread that warns clients
047: * when they need to update the screen. Clients that
048: * need a wakeup call need to call Notify().
049: *
050: * @version 1.20, 07/01/98
051: * @author Arthur van Hoff
052: */
053: public class ScreenUpdater extends Thread {
054: private ScreenUpdaterEntry first;
055: /**
056: * The screen updater.
057: */
058: public final static ScreenUpdater updater = initScreenUpdater();
059:
060: private static ScreenUpdater initScreenUpdater() {
061: return (ScreenUpdater) java.security.AccessController
062: .doPrivileged(new java.security.PrivilegedAction() {
063: public Object run() {
064: ScreenUpdater scr = new ScreenUpdater();
065: scr.setContextClassLoader(null);
066: return scr;
067: }
068: });
069: }
070:
071: private static ThreadGroup getScreenUpdaterThreadGroup() {
072: ThreadGroup g = currentThread().getThreadGroup();
073: while ((g.getParent() != null)
074: && (g.getParent().getParent() != null)) {
075: g = g.getParent();
076: }
077: return g;
078: }
079:
080: /**
081: * Constructor. Starts the thread.
082: */
083: private ScreenUpdater() {
084: super (getScreenUpdaterThreadGroup(), "Screen Updater");
085: start();
086: }
087:
088: /**
089: * Update the next client
090: */
091: private synchronized ScreenUpdaterEntry nextEntry()
092: throws InterruptedException {
093: while (true) {
094: if (first == null) {
095: wait();
096: continue;
097: }
098: long delay = first.when - System.currentTimeMillis();
099: if (delay <= 0) {
100: ScreenUpdaterEntry entry = first;
101: first = first.next;
102: return entry;
103: }
104: wait(delay);
105: }
106: }
107:
108: /**
109: * The main body of the screen updater.
110: */
111: public void run() {
112: try {
113: while (true) {
114: setPriority(NORM_PRIORITY - 1);
115: ScreenUpdaterEntry entry = nextEntry();
116: setPriority(NORM_PRIORITY + 1);
117: try {
118: entry.client.updateClient(entry.arg);
119: } catch (Throwable e) {
120: e.printStackTrace();
121: }
122: // Because this thread is permanent, we don't want to defeat
123: // the garbage collector by having dangling references to
124: // objects we no longer care about. Clear out entry so that
125: // when we go back to sleep in nextEntry we won't hold a
126: // dangling reference to the previous entry we processed.
127: entry = null;
128: }
129: } catch (InterruptedException e) {
130: }
131: }
132:
133: /**
134: * Notify the screen updater that a client needs
135: * updating. As soon as the screen updater is
136: * scheduled to run it will ask all of clients that
137: * need updating to update the screen.
138: */
139: public void notify(UpdateClient client) {
140: notify(client, 100, null);
141: }
142:
143: public synchronized void notify(UpdateClient client, long delay) {
144: notify(client, delay, null);
145: }
146:
147: public synchronized void notify(UpdateClient client, long delay,
148: Object arg) {
149: long when = System.currentTimeMillis() + delay;
150: long nextwhen = (first != null) ? first.when : -1L;
151: if (first != null) {
152: if ((first.client == client) && (first.arg == arg)) {
153: if (when >= first.when) {
154: return;
155: }
156: first = first.next;
157: } else {
158: for (ScreenUpdaterEntry e = first; e.next != null; e = e.next) {
159: if ((e.next.client == client)
160: && (e.next.arg == arg)) {
161: if (when >= e.next.when) {
162: return;
163: }
164: e.next = e.next.next;
165: break;
166: }
167: }
168: }
169: }
170: if ((first == null) || (first.when > when)) {
171: first = new ScreenUpdaterEntry(client, when, arg, first);
172: } else {
173: for (ScreenUpdaterEntry e = first;; e = e.next) {
174: if ((e.next == null) || (e.next.when > when)) {
175: e.next = new ScreenUpdaterEntry(client, when, arg,
176: e.next);
177: break;
178: }
179: }
180: }
181: if (nextwhen != first.when) {
182: super .notify();
183: }
184: }
185:
186: /**
187: * Remove any pending entries for the specified client.
188: * This method is normally called by the client's dispose() method.
189: */
190: public synchronized void removeClient(UpdateClient client) {
191: ScreenUpdaterEntry entry = first;
192: ScreenUpdaterEntry prev = null;
193: while (entry != null) {
194: if (entry.client.equals(client)) {
195: if (prev == null) {
196: first = entry.next;
197: } else {
198: prev.next = entry.next;
199: }
200: } else {
201: prev = entry;
202: }
203: entry = entry.next;
204: }
205: }
206: }
|