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

net.sourceforge.jtds.util.TimerThread Maven / Gradle / Ivy

Go to download

jTDS is an open source 100% pure Java (type 4) JDBC 3.0 driver for Microsoft SQL Server (6.5, 7, 2000, 2005, 2008, 2012) and Sybase ASE (10, 11, 12, 15). jTDS is based on FreeTDS and is currently the fastest production-ready JDBC driver for SQL Server and Sybase. jTDS is 100% JDBC 3.0 compatible, supporting forward-only and scrollable/updateable ResultSets and implementing all the DatabaseMetaData and ResultSetMetaData methods.

There is a newer version: 1.3.1
Show newest version
// jTDS JDBC Driver for Microsoft SQL Server and Sybase
// Copyright (C) 2004 The jTDS Project
//
// This library 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.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
package net.sourceforge.jtds.util;

import java.util.LinkedList;
import java.util.ListIterator;

/**
 * Simple timer class used to implement login and query timeouts.
 * 

* This thread runs as a Daemon thread to ensure that the java VM will exit * correctly when normal execution is complete. *

* It provides both a singleton implementation and a default constructor for * the case when more than one timer thread is desired. * * @author Alin Sinpalean * @author Mike Hutchinson * @version $Id: TimerThread.java,v 1.5.2.1 2009/07/23 16:18:51 ickzon Exp $ */ public class TimerThread extends Thread { /** * Interface to be implemented by classes that request timer services. */ public interface TimerListener { /** * Event to be fired when the timeout expires. */ void timerExpired(); } /** * Internal class associating a login or query timeout value with a target * TimerListener. */ private static class TimerRequest { /** The time when this timeout will expire. */ final long time; /** Target to notify when the timeout expires. */ final TimerListener target; /** * Create a TimerRequest. * * @param timeout the desired timeout in milliseconds * @param target the target object; one of SharedSocket or * TdsCore * @throws IllegalArgumentException if the timeout is negative or 0 */ TimerRequest(int timeout, TimerListener target) { if (timeout <= 0) { throw new IllegalArgumentException("Invalid timeout parameter " + timeout); } this.time = System.currentTimeMillis() + (timeout); this.target = target; } } /** Singleton instance. */ private static TimerThread instance; /** List of TimerRequests to execute, ordered by time. */ private final LinkedList timerList = new LinkedList(); /** Time when the first request time out should occur. */ private long nextTimeout; /** * Singleton getter. */ public static synchronized TimerThread getInstance() { if (instance == null) { instance = new TimerThread(); instance.start(); } return instance; } /** * Construct a new TimerThread instance. */ public TimerThread() { // Set the thread name super("jTDS TimerThread"); // Ensure that this thread does not prevent the VM from exiting this.setDaemon(true); } /** * Execute the TimerThread main loop. */ public void run() { synchronized (timerList) { while (true) { try { if (nextTimeout == 0) { // If nextTimeout == 0 (i.e. there are no more requests // in the queue) wait indefinitely -- wait(0) timerList.wait(0); } else { long ms = nextTimeout - System.currentTimeMillis(); if (ms > 0) { // positive timeout, wait appropriately timerList.wait(ms); } } // Fire expired timeout requests long time = System.currentTimeMillis(); while (!timerList.isEmpty()) { // Examine the head of the list and see // if the timer has expired. TimerRequest t = (TimerRequest) timerList.getFirst(); if (t.time > time) { break; // No timers have expired } // Notify target of timeout t.target.timerExpired(); // Remove the fired timeout request timerList.removeFirst(); } // Determine next timeout updateNextTimeout(); } catch (InterruptedException e) { // nop } } } } /** * Add a timer request to the queue. *

* The queue is ordered by time so that the head of the list is always the * first timer to expire. * * @param timeout the interval in milliseconds after which the timer will * expire * @param l TimerListener to be notified on timeout * @return a handle to the timer request, that can later be used with * cancelTimer */ public Object setTimer(int timeout, TimerListener l) { // Create a new timer request TimerRequest t = new TimerRequest(timeout, l); synchronized (timerList) { if (timerList.isEmpty()) { // List was empty, just add new request timerList.add(t); } else { // Tiny optimization; new requests will usually go to the end TimerRequest crt = (TimerRequest) timerList.getLast(); if (t.time >= crt.time) { timerList.addLast(t); } else { // Iterate the list and insert it into the right place for (ListIterator li = timerList.listIterator(); li.hasNext(); ) { crt = (TimerRequest) li.next(); if (t.time < crt.time) { li.previous(); li.add(t); break; } } } } // If this request is now the first in the list, interrupt timer if (timerList.getFirst() == t) { nextTimeout = t.time; this.interrupt(); } } // Return the created request as timer handle return t; } /** * Remove a redundant timer before it expires. * * @param handle handle to the request to be removed from the queue (a * TimerRequest instance) * @return true if timer had not expired */ public boolean cancelTimer(Object handle) { TimerRequest t = (TimerRequest) handle; synchronized (timerList) { boolean result = timerList.remove(t); if (nextTimeout == t.time) { updateNextTimeout(); } return result; } } /** * Check whether a timer has expired. * * @param handle handle to the request to be checked for expiry (a * TimerRequest instance) * @return true if timer has expired */ public boolean hasExpired(Object handle) { TimerRequest t = (TimerRequest) handle; synchronized (timerList) { return !timerList.contains(t); } } /** Internal method that updates the value of {@link #nextTimeout}. */ private void updateNextTimeout() { nextTimeout = timerList.isEmpty() ? 0 : ((TimerRequest) timerList.getFirst()).time; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy