/******************************************************************************* * Copyright (c) 1997, 2008 by ProSyst Software GmbH * http://www.prosyst.com * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ProSyst Software GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.equinox.internal.util.impl.tpt.timer; /** * @author Pavlin Dobrev * @version 1.0 */ class TimerQueue { static final int POOL_SIZE = 20; QueueElement[] pool = new QueueElement[POOL_SIZE]; int filled = 0; QueueElement first; QueueElement lastInserted; TimerQueue() { } /** * Adds a new task to the priority queue. */ void add(TimerQueueNode task) { QueueElement toAdd = getQueueElement(); toAdd.node = task; if (first == null) { first = toAdd; } else { insertElement(toAdd); } } /** * Return the "head task" of the priority queue. (The head task is an task * with the lowest nextExecutionTime.) */ TimerQueueNode getMin() { return (first != null) ? first.node : null; } /** * Remove the head task from the priority queue. */ void removeMin() { if (first != null) { if (lastInserted == first) { lastInserted = null; } if (filled < POOL_SIZE) { QueueElement toFree = first; first = first.next; freeQueueElement(toFree); } else { first = first.next; } } } /** * Sets the nextExecutionTime associated with the head task to the specified * value, and adjusts priority queue accordingly. */ void rescheduleMin(long newTime) { first.node.runOn = newTime; if (first.next != null) { if (lastInserted == first) { lastInserted = null; } QueueElement el = first; first = first.next; el.next = null; insertElement(el); } } /** * Returns true if the priority queue contains no elements. */ boolean isEmpty() { return first == null; } /** * Removes all elements from the priority queue. */ void clear() { while (first != null) { first.node.returnInPool(); first = first.next; } lastInserted = null; } void insertElement(QueueElement newElement) { if (first.node.runOn >= newElement.node.runOn) { /* private case - insert in the beginning of the queue */ newElement.next = first; first = newElement; } else if (lastInserted != null) { if (lastInserted.node.runOn == newElement.node.runOn) { QueueElement tmp = lastInserted.next; lastInserted.next = newElement; newElement.next = tmp; } else if (lastInserted.node.runOn > newElement.node.runOn) { // System.out.println("insert 1"); doInsertElement(first, newElement); } else { // System.out.println("insert 2"); doInsertElement(lastInserted, newElement); } } else { // System.out.println("insert 3"); doInsertElement(first, newElement); } } /** * elToInsert should not be placed before firstEl, because firstEl may not * be the first element of the queue */ void doInsertElement(QueueElement firstEl, QueueElement elToInsert) { QueueElement tmp = firstEl; QueueElement prev = firstEl; while (tmp != null && tmp.node.runOn < elToInsert.node.runOn) { prev = tmp; tmp = tmp.next; } if (tmp == null) { /* reached the end of the queue */ prev.next = elToInsert; } else { prev.next = elToInsert; elToInsert.next = tmp; } lastInserted = elToInsert; } void removeTimerNode(TimerQueueNode node) { QueueElement tmp = first; QueueElement prev = null; while (tmp != null) { if (node.listener == tmp.node.listener && node.event == tmp.node.event) { if (prev != null) { if (lastInserted == tmp) { lastInserted = prev; } prev.next = tmp.next; if (filled < POOL_SIZE) { freeQueueElement(tmp); } } else { /* removing the first element */ if (lastInserted == first) { lastInserted = null; } if (filled < POOL_SIZE) { QueueElement toFree = first; first = first.next; freeQueueElement(toFree); } else { first = first.next; } } break; } prev = tmp; tmp = tmp.next; } } private QueueElement getQueueElement() { return (filled > 0) ? pool[--filled] : new QueueElement(); } private void freeQueueElement(QueueElement toFree) { if (filled < POOL_SIZE) { pool[filled] = toFree; filled++; toFree.next = null; toFree.node = null; } } private class QueueElement { QueueElement next; TimerQueueNode node; public QueueElement() { } } }