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

com.sun.tv.net.util.Timer Maven / Gradle / Ivy

The newest version!
/*
 * @(#)Timer.java	1.22 97/03/06 SMI
 *
 * Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 */

//
// Timer.java
//
// This class provides a general purpose event timer.
//
// How to use:
//
// 1. Subclass Timer and implement your own callback(long) method.
// 2. Instantiate your subclass:
//        FooTimer foo = new FooTimer();
// 3. Start the timer to go off n msec in the future:
//        foo.start(n);
//    Your callback() method will be called with this interval expires.
// 4. You can call stop() to cancel the timer:
//        foo.stop();
// 5. Calling start(long) on a timer in progress will cancel the current
//    timer and start a new one with the given delay.
//
// sritchie -- Oct 95
//
// notes
//
// We implement this using a sorted priority list.  Sort key is the
// system absolute time that the timer callback should be invoked.
//
// The priority list is currently a simple double-linked list.  Starts
// are O(n) linear search, expiries are O(1), stops are O(1).  Might want
// to use a heap if the number of timers gets large.
//


package com.sun.tv.net.util;



class TimerThread extends SystemThread {

    TimerThread() {
	super("JavaOS Timer Thread",TimerThreadPriority);
    }

    public void run() {
	for (;;) {
	    try {
		Timer.doit();
	    } catch (OutOfMemoryError e) {
		// don't printStackTrace() for OutOfMemoryError -- might
		// not have enough memory to do that.
	    } catch (Throwable t) {
		// don't let this important system thread exit.
		try {
		    t.printStackTrace();
		} catch (OutOfMemoryError e) {
		}
	    }
	}
    }
}


public abstract class Timer {

    public Timer() {
    }
    
    // Users of the Timer class must implement this method to
    // receive their timer expiry callbacks.
    // delta is the number of milliseconds since the timer was started.
    public abstract void callback(long delta);

    
    //----------------------------------------------------------------------

    public boolean isStarted() {
	
	// we maintain the expiry field such that if it is zero,
	// the timer is guaranteed to be not in use.
	return (expiry != 0);
    }

    private void remove() {

	// remove this timer from the queue.
	//dprint("stop expiry: " + expiry);

	expiry = 0;

	if (this == timerHead) {
	    timerHead.prev = null;
	    timerHead = next;
	} else {
	    prev.next = next;
	}

	if (next != null) {
	    next.prev = prev;
	}

    }

    // stop this timer event
    public void stop() {

	synchronized (timerThread) {
	    if (isStarted() == true) {
		remove();
	    }
	}
    }

    //----------------------------------------------------------------------
    
    public void start(long sleepTime) {

	synchronized (timerThread) {
	    if (isStarted() == true) {
		remove();
	    }

	    startedAt = System.currentTimeMillis();
	    expiry = startedAt + sleepTime;	

	    //dprint("start expiry: " + expiry);

	    Timer timer;
	
	    if (timerHead != null) {

		// search for the insertion point.
		timer = timerHead;
		while (timer.expiry <= expiry) {
    
		    if (timer.next == null) {
			//dprint("insert at tail");
			timer.next = this;
			prev = timer;
			next = null;
			return;
		    }
		    timer = timer.next;
		}
	
		// insert us before current timer
		next = timer;
		if (timer.prev == null) {

		    prev = null;
		    timerHead = this;
		
		    // notify TimerThread that something has changed at the
		    // beginning of the list.
		    //dprint("inserted before head, signalling timerThread");

		    timerThread.notify();

		} else {
		    prev = timer.prev;
		    timer.prev.next = this;
		}
	    
		timer.prev = this;

	    } else {
		next = null;
		prev = null;
		timerHead = this;
		
		// notify TimerThread that something has changed at the
		// beginning of the list.
		//dprint("insert on empty, signalling timerThread");

		timerThread.notify();
	    }

	    return;
	}
    }
    
    //----------------------------------------------------------------------
    
    static void doit() throws InterruptedException {

	Timer timer = null;
	long delta = 0;

	synchronized (timerThread) {

	    long time = System.currentTimeMillis();

	    // Loop until the timer event at the head of the queue expires.
	    while (timerHead == null || timerHead.expiry > time) {
		    
		long timeout;
		if (timerHead != null) {
		    timeout = timerHead.expiry - time;
		} else {
		    timeout = 0;
		}

		// wait for a timer event to be posted
		timerThread.wait(timeout);

		time = System.currentTimeMillis();
	    }

	    // If we get here then an expired event is sitting at the
	    // head of the queue.
	    timer = timerHead;

	    // remove the first timer element
	    timerHead = timerHead.next;
	    if (timerHead != null)
		timerHead.prev = null;

	    //dprint("Expiring at " + time + " for " + timer.owner +
	    //      " started at " + timer.startedAt + " expiry:" +
	    //      timer.expiry);

	    // this means this timer is dequeued.
	    timer.expiry = 0;

	    // compute time between timer start and expiry time.
	    delta = time - timer.startedAt;
	}

	// Now that we have released the monitor, callback to the
	// user's event handler telling it how long it waited.
	timer.callback(delta);
    }

    // This method is called by sun.javaos.Clock.setTime() to update the
    // Timer event queue's notion of what the current time is.
    // eg, in the boot process when we get the current time from the
    // network and reset it.
    // delta is the time change in msec.
    static void resyncTime(long delta) {

	synchronized (timerThread) {
	    Timer timer = timerHead;

	    while (timer != null) {
		// adjust the expiry time by the given delta.
		timer.expiry += delta;
		timer.startedAt += delta;

		timer = timer.next;
	    }
	}
    }


    //----------------------------------------------------------------------
    
    private static boolean debug = false;

    private static void dprint(String mess) {
        if (debug) {
            System.err.println("Timer: " + mess);
        }
    }

    //----------------------------------------------------------------------
    
    private static Timer timerHead;
    private static TimerThread timerThread;
        
    private Timer next;
    private Timer prev;
    
    private long expiry;
    private long startedAt;
    
    static {
	timerThread = new TimerThread();
	timerThread.start();
    }
}

/*
 * This code is used to test the Timer implementation.
 *
class FooTimer extends Timer {

    protected void callback(long delta) {
	System.out.println("FooTimer: expired "+delta+" msec.");
	TimerTest.numCallbacks--;
    }
}


class TimerTest {

    public static int numCallbacks;

    public static void main(String argv[]) {

        Random rand = new Random();

        for (int i = 0; i < 10000; i++) {

            if (i != 0) {
                System.out.println("*** starting again");
            }

            for (numCallbacks = 0; numCallbacks < 5; numCallbacks++) {
		String s = "Gimple " + numCallbacks;
                Timer t = new FooTimer(s);

                int time = rand.nextInt() % 5000;
                if (time < 0) {
		    time = -time;
                }

	        System.out.println("Starting "+s+" " + time + " msec.");
		t.start(time);

                if (rand.nextInt() < 0) {
                    numCallbacks--;
		    System.out.println("Stopping " + s);
                    t.stop();
                }
            }

            while (numCallbacks > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException intr) {
                    // do nothing
                }
            }

        }
    }
}*/






© 2015 - 2025 Weber Informatics LLC | Privacy Policy