All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wings.util.TimerQueue Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2000,2005 wingS development team.
 *
 * This file is part of wingS (http://wingsframework.org).
 *
 * wingS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * Please see COPYING for the complete licence.
 */
package org.wings.util;

/*
 * Die Klasse ist praktisch von der Swing Implementierung
 * abgeleitet. Leider brauch ich einen Timer, der auch innerhalb des
 * Swing Event Threads Impulse gibt. Deshalb angepasst. Ich hoffe das
 * gibt keine Problemen mit dem Swing Team.
 */

/**
 * @author Armin Haaf
 */
public final class TimerQueue
        implements Runnable {
    /*
     * Es gibt nur eine Queue pro Application.
     */
    private static TimerQueue sharedInstance = new TimerQueue();

    private Timer firstTimer;
    private boolean running;

    /*
     * Es gibt nur eine TimerQueue pro Application.
     */
    private TimerQueue() {
        super();

        // Now start the TimerQueue thread.
        start();
    }

    /*
     * Die eine Queue!!
     */
    public static TimerQueue sharedInstance() {
        return sharedInstance;
    }

    private synchronized void start() {
        System.err.println("Timer started");
        if (running) {
            throw new RuntimeException("Can't start a TimerQueue that is already running");
        } else {
            Thread timerThread = new Thread(this, "TimerQueue");

            try {
                timerThread.setDaemon(true);
            } catch (SecurityException e) {}
            timerThread.start();
            running = true;
        }
    }

    private synchronized void stop() {
        running = false;
        notifyAll();
    }

    public synchronized void addTimer(Timer timer, long expirationTime) {

        // If the Timer is already in the queue, then ignore the add.
        if (timer.running) {
            return;
        }

        Timer previousTimer = null;
        Timer nextTimer = firstTimer;

        // Insert the Timer into the linked list in the order they will
        // expire.  If two timers expire at the same time, put the newer entry
        // later so they expire in the order they came in.

        while (nextTimer != null) {
            if (nextTimer.expirationTime > expirationTime)
                break;

            previousTimer = nextTimer;
            nextTimer = nextTimer.nextTimer;
        }

        if (previousTimer == null)
            firstTimer = timer;
        else
            previousTimer.nextTimer = timer;

        timer.expirationTime = expirationTime;
        timer.nextTimer = nextTimer;
        timer.running = true;
        notifyAll();
    }

    public synchronized void removeTimer(Timer timer) {

        if (!timer.running)
            return;

        Timer previousTimer = null;
        Timer nextTimer = firstTimer;
        boolean found = false;

        while (nextTimer != null) {
            if (nextTimer == timer) {
                found = true;
                break;
            }

            previousTimer = nextTimer;
            nextTimer = nextTimer.nextTimer;
        }

        if (!found)
            return;

        if (previousTimer == null)
            firstTimer = timer.nextTimer;
        else
            previousTimer.nextTimer = timer.nextTimer;

        timer.expirationTime = 0;
        timer.nextTimer = null;
        timer.running = false;
    }

    public synchronized boolean containsTimer(Timer timer) {
        return timer.running;
    }

    // If there are a ton of timers, this method may never return.  It loops
    // checking to see if the head of the Timer list has expired.  If it has,
    // it posts the Timer and reschedules it if necessary.

    public synchronized long postExpiredTimers() {
        long timeToWait;

        // The timeToWait we return should never be negative and only be zero
        // when we have no Timers to wait for.

        do {
            Timer timer = firstTimer;
            if (timer == null)
                return 0;

            long currentTime = System.currentTimeMillis();
            timeToWait = timer.expirationTime - currentTime;

            if (timeToWait <= 0) {
                try {
                    timer.post();  // have timer post an event
                } catch (SecurityException e) {}

                // remove the timer from the queue
                removeTimer(timer);

                // This tries to keep the interval uniform at the cost of
                // drift.
                if (timer.isRepeats()) {
                    addTimer(timer, currentTime + timer.getDelay());
                }
            }

            // Allow other threads to call addTimer() and removeTimer()
            // even when we are posting Timers like mad.  Since the wait()
            // releases the lock, be sure not to maintain any state
            // between iterations of the loop.

            try {
                wait(1);
            } catch (InterruptedException e) {
            }
        } while (timeToWait <= 0);

        return timeToWait;
    }

    @Override
    public synchronized void run() {

        try {
            while (running) {
                long timeToWait = postExpiredTimers();
                try {
                    wait(timeToWait);
                } catch (InterruptedException e) { }
            }
        } catch (ThreadDeath td) {
            running = false;
            // Mark all the timers we contain as not being queued.
            Timer timer = firstTimer;
            while (timer != null) {
                timer.eventQueued = false;
                timer = timer.nextTimer;
            }
            sharedInstance.start();
            throw td;
        }
    }

    public synchronized String toString() {

        StringBuilder buf = new StringBuilder();
        buf.append("TimerQueue (");

        Timer nextTimer = firstTimer;
        while (nextTimer != null) {
            buf.append(nextTimer.toString());

            nextTimer = nextTimer.nextTimer;
            if (nextTimer != null)
                buf.append(", ");
        }

        buf.append(')');
        return buf.toString();
    }
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy