Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2005-2006 Laf-Widget Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Laf-Widget Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jvnet.lafwidget.utils;
import java.util.*;
/**
* Delta queue. Follows a standard approach from OS world for effeciently
* keeping tracks of scheduled events.
*
* @author Kirill Grouchnikov
*/
public class DeltaQueue {
/**
* Base class for entries in a {@link DeltaQueue}.
*
* @author Kirill Grouchnikov
*/
public static abstract class Deltable {
/**
* Delta in application specific units.
*/
protected int delta;
/**
* Creates a new delta.
*/
public Deltable() {
super();
}
/**
* Returns the current delta in application specific units.
*
* @return The current delta in application specific units.
*/
public int getDelta() {
return delta;
}
/**
* Sets the new value of delta in application specific units.
*
* @param delta
* New value of delta in application specific units.
*/
public void setDelta(int delta) {
this.delta = delta;
}
/**
* Increments the delta value by the specified amount.
*
* @param diff
* Amount for incrementing the delta value.
*/
public void incrementDelta(int diff) {
this.delta += diff;
}
/**
* Decrements the delta value by the specified amount.
*
* @param diff
* Amount for decrementing the delta value.
*/
public void decrementDelta(int diff) {
this.delta -= diff;
}
}
/**
* Interface for comparing two delta instances.
*
* @author Kirill Grouchnikov.
*/
public static interface DeltaMatcher {
/**
* Returns true if the specified delta matches some
* criteria.
*
* @param deltable
* Delta.
* @return true if the specified delta matches some
* criteria, false otherwise.
*/
public boolean matches(Deltable deltable);
}
/**
* List of entries. Contains {@link Deltable}s.
*/
protected ArrayList queue;
/**
* Constructs a new empty non-blocking synchronized delta queue.
*/
public DeltaQueue() {
this.queue = new ArrayList();
}
/**
* Queues the specified deltable. The specified deltable is placed somewhere
* in the queue based on the initial value of its delta. Note that when this
* method returns, the value of a {@link Deltable#getDelta()} may have
* changed. Do not reuse or change the passed deltable after this method
* returns.
*
* @param deltable
* Deltable.
*/
public synchronized void queue(Deltable deltable) {
// locate the correct position in a time-difference queue
int currDiff = deltable.getDelta();
for (int i = 0; i < this.queue.size(); i++) {
Deltable currDeltable = (Deltable) this.queue.get(i);
currDiff -= currDeltable.getDelta();
if (currDiff > 0) {
continue;
}
if (currDiff == 0) {
// scan until the next diff is more than 0
deltable.setDelta(0);
for (int j = i + 1; j < this.queue.size(); j++) {
Deltable nextDeltable = (Deltable) this.queue.get(j);
if (nextDeltable.getDelta() > 0) {
// put just before it
this.queue.add(j, deltable);
return;
}
}
// if here - add at the end
this.queue.add(this.queue.size(), deltable);
return;
}
deltable.setDelta(currDiff + currDeltable.getDelta());
currDeltable.decrementDelta(deltable.getDelta());
this.queue.add(i, deltable);
return;
}
// put last
deltable.setDelta(currDiff);
this.queue.add(this.queue.size(), deltable);
}
/**
* Returns all deltables that have at most specified delay left. The
* returned list may be empty.
*
* @param delay
* Delay.
* @return The possibly empty list of all deltables that have at most
* specified delay left.
*/
public synchronized List dequeue(int delay) {
List result = new LinkedList();
while (this.queue.size() > 0) {
Deltable next = (Deltable) this.queue.get(0);
int timeToExpire = next.getDelta();
next.decrementDelta(delay);
if (next.getDelta() > 0) {
break;
}
if (timeToExpire > 0)
delay -= timeToExpire;
result.add(next);
this.queue.remove(0);
}
return result;
}
/**
* Removes all deltas matching the specified matcher.
*
* @param matcher
* Delta matcher.
*/
public synchronized void removeMatching(DeltaMatcher matcher) {
// start from the end
while (true) {
int toRemoveInd = -1;
Deltable toRemove = null;
for (int i = this.queue.size() - 1; i >= 0; i--) {
Deltable deltable = (Deltable) this.queue.get(i);
if (!matcher.matches(deltable))
continue;
toRemoveInd = i;
toRemove = deltable;
break;
}
if (toRemoveInd >= 0) {
if (toRemoveInd < (this.queue.size() - 1)) {
Deltable next = (Deltable) this.queue.get(toRemoveInd + 1);
next.incrementDelta(toRemove.getDelta());
}
this.queue.remove(toRemoveInd);
} else {
return;
}
}
}
/**
* Dumps the contents of the delta queue.
*/
public void dump() {
System.out.println("Dump");
for (int i = 0; i < this.queue.size(); i++) {
System.out.println("\t" + this.queue.get(i));
}
}
/**
* Test class.
*
* @author Kirill Grouchnikov
*/
private static class DeltableTest extends Deltable {
/**
* ID.
*/
private int id;
/**
* Creates a test delta.
*
* @param id
* ID.
* @param delta
* Delta.
*/
public DeltableTest(int id, int delta) {
super();
this.id = id;
this.delta = delta;
}
public String toString() {
return this.id + ":" + this.delta;
}
}
/**
* For testing.
*
* @param args
* Ignored.
*/
public static void main(String[] args) {
DeltaQueue dq = new DeltaQueue();
DeltableTest tpi11 = new DeltableTest(11, 100);
dq.queue(tpi11);
dq.dump();
DeltableTest tpi12 = new DeltableTest(12, 100);
dq.queue(tpi12);
dq.dump();
DeltableTest tpi21 = new DeltableTest(21, 200);
dq.queue(tpi21);
dq.dump();
DeltableTest tpi31 = new DeltableTest(31, 300);
dq.queue(tpi31);
dq.dump();
DeltableTest tpi13 = new DeltableTest(13, 100);
dq.queue(tpi13);
dq.dump();
DeltableTest tpi22 = new DeltableTest(22, 200);
dq.queue(tpi22);
dq.dump();
DeltableTest tpi25 = new DeltableTest(25, 250);
dq.queue(tpi25);
dq.dump();
DeltableTest tpi51 = new DeltableTest(51, 500);
dq.queue(tpi51);
dq.dump();
DeltableTest tpi05 = new DeltableTest(5, 50);
dq.queue(tpi05);
dq.dump();
List gr150 = dq.dequeue(100);
System.out.println("Dump 150");
for (int i = 0; i < gr150.size(); i++) {
DeltableTest tpi = (DeltableTest) gr150.get(i);
System.out.println("\t" + tpi);
}
dq.dump();
dq.removeMatching(new DeltaMatcher() {
public boolean matches(Deltable deltable) {
return ((DeltableTest) deltable).id < 30;
}
});
dq.dump();
TrackableThread.requestStopAllThreads();
}
}