/* * @(#)ScreenUpdater.java 1.30 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 sun.awt; class ScreenUpdaterEntry { UpdateClient client; long when; ScreenUpdaterEntry next; Object arg; ScreenUpdaterEntry(UpdateClient client, long when, Object arg, ScreenUpdaterEntry next) { this.client = client; this.when = when; this.arg = arg; this.next = next; } } /** * A seperate low priority thread that warns clients * when they need to update the screen. Clients that * need a wakeup call need to call Notify(). * * @version 1.20, 07/01/98 * @author Arthur van Hoff */ public class ScreenUpdater extends Thread { private ScreenUpdaterEntry first; /** * The screen updater. */ public final static ScreenUpdater updater = initScreenUpdater(); private static ScreenUpdater initScreenUpdater() { return (ScreenUpdater) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { ScreenUpdater scr = new ScreenUpdater(); scr.setContextClassLoader(null); return scr; } } ); } private static ThreadGroup getScreenUpdaterThreadGroup() { ThreadGroup g = currentThread().getThreadGroup(); while ((g.getParent() != null) && (g.getParent().getParent() != null)) { g = g.getParent(); } return g; } /** * Constructor. Starts the thread. */ private ScreenUpdater() { super(getScreenUpdaterThreadGroup(), "Screen Updater"); start(); } /** * Update the next client */ private synchronized ScreenUpdaterEntry nextEntry() throws InterruptedException { while (true) { if (first == null) { wait(); continue; } long delay = first.when - System.currentTimeMillis(); if (delay <= 0) { ScreenUpdaterEntry entry = first; first = first.next; return entry; } wait(delay); } } /** * The main body of the screen updater. */ public void run() { try { while (true) { setPriority(NORM_PRIORITY - 1); ScreenUpdaterEntry entry = nextEntry(); setPriority(NORM_PRIORITY + 1); try { entry.client.updateClient(entry.arg); } catch (Throwable e) { e.printStackTrace(); } // Because this thread is permanent, we don't want to defeat // the garbage collector by having dangling references to // objects we no longer care about. Clear out entry so that // when we go back to sleep in nextEntry we won't hold a // dangling reference to the previous entry we processed. entry = null; } } catch (InterruptedException e) {} } /** * Notify the screen updater that a client needs * updating. As soon as the screen updater is * scheduled to run it will ask all of clients that * need updating to update the screen. */ public void notify(UpdateClient client) { notify(client, 100, null); } public synchronized void notify(UpdateClient client, long delay) { notify(client, delay, null); } public synchronized void notify(UpdateClient client, long delay, Object arg) { long when = System.currentTimeMillis() + delay; long nextwhen = (first != null) ? first.when : -1L; if (first != null) { if ((first.client == client) && (first.arg == arg)) { if (when >= first.when) { return; } first = first.next; } else { for (ScreenUpdaterEntry e = first; e.next != null; e = e.next) { if ((e.next.client == client) && (e.next.arg == arg)) { if (when >= e.next.when) { return; } e.next = e.next.next; break; } } } } if ((first == null) || (first.when > when)) { first = new ScreenUpdaterEntry(client, when, arg, first); } else { for (ScreenUpdaterEntry e = first;; e = e.next) { if ((e.next == null) || (e.next.when > when)) { e.next = new ScreenUpdaterEntry(client, when, arg, e.next); break; } } } if (nextwhen != first.when) { super.notify(); } } /** * Remove any pending entries for the specified client. * This method is normally called by the client's dispose() method. */ public synchronized void removeClient(UpdateClient client) { ScreenUpdaterEntry entry = first; ScreenUpdaterEntry prev = null; while (entry != null) { if (entry.client.equals(client)) { if (prev == null) { first = entry.next; } else { prev.next = entry.next; } } else { prev = entry; } entry = entry.next; } } }