001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.utils;
007:
008: import java.util.EmptyStackException;
009: import java.util.Stack;
010:
011: /**
012: * A simple FILO stack that has MIN/MAX capacity and
013: * that blocks if either push/pop would result
014: * in violation of these limits.
015: * Default values for min/max are 0/infinite
016: * @author Peter Kharchenko
017: */
018:
019: public class BlockingStack {
020: int maxSize;
021: int minSize;
022:
023: volatile Stack stack = null;
024:
025: BlockingStack() {
026: maxSize = -1;
027: minSize = 0;
028: stack = new Stack();
029: }
030:
031: /**
032: * Construct a new blocking stack with predefined max/min limits
033: */
034: BlockingStack(int min, int max) {
035: this ();
036: maxSize = max;
037: minSize = min;
038: }
039:
040: BlockingStack(int max) {
041: this (0, max);
042: }
043:
044: public synchronized boolean empty() {
045: return stack.empty();
046: }
047:
048: /**
049: * Add new object to the top of the stack
050: * @param o object to be placed on the stack
051: */
052: public synchronized void push(Object o) throws InterruptedException {
053: while (stack.size() >= maxSize && maxSize != -1) {
054: wait();
055: }
056: stack.push(o);
057: notifyAll();
058: }
059:
060: /**
061: * Remove object from the top of the stack
062: * @throws InterruptedException if the wait was interrupted
063: */
064: public synchronized Object pop() throws InterruptedException {
065: while (stack.size() <= minSize) {
066: wait();
067: }
068: notifyAll();
069: return stack.pop();
070: }
071:
072: /**
073: * Regular, non-blocking pop
074: */
075: public synchronized Object nonBlockingPop()
076: throws EmptyStackException {
077: Object o = stack.pop();
078: notifyAll();
079: return o;
080: }
081:
082: /**
083: * Regular, non-blocking push.
084: */
085: public synchronized boolean nonBlockingPush(Object o) {
086: if (stack.size() > maxSize && maxSize != -1)
087: return false;
088: else
089: stack.push(o);
090: notifyAll();
091: return true;
092: }
093:
094: /**
095: * Set the stack limits.
096: * To specify a stack without an upper bound (that is max=inifinity) use max value of -1
097: */
098: public synchronized void setLimits(int max, int min) {
099: maxSize = max;
100: minSize = min;
101: notifyAll();
102: }
103:
104: /**
105: * Find and remove a specific object from the stack
106: */
107: public synchronized boolean remove(Object o) {
108: return stack.remove(o);
109: }
110:
111: public int getMaxSize() {
112: return maxSize;
113: }
114:
115: public int getMinSize() {
116: return minSize;
117: }
118:
119: public synchronized void setMaxSize(int max) {
120: maxSize = max;
121: notifyAll();
122: }
123:
124: public synchronized void setMinSize(int min) {
125: minSize = min;
126: notifyAll();
127: }
128:
129: public synchronized int size() {
130: return stack.size();
131: }
132: }
|