0001: /*
0002: * This software is released under a licence similar to the Apache Software Licence.
0003: * See org.logicalcobwebs.proxool.package.html for details.
0004: * The latest version is available at http://proxool.sourceforge.net
0005: *
0006: * THIS CLASS WAS COPIED FROM THE JAKARTA COMMONS COLLECTIONS
0007: * VERSION 2.1. WE ARE GRATEFUL FOR THEIR CONTRIBUTION. We decided
0008: * not to introduce the whole library as a dependency at this stage but might decide
0009: * to at a later date.
0010: */
0011:
0012: /*
0013: * $Header: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/util/FastArrayList.java,v 1.4 2003/03/10 23:43:18 billhorsman Exp $
0014: * $Revision: 1.4 $
0015: * $Date: 2003/03/10 23:43:18 $
0016: *
0017: * ====================================================================
0018: *
0019: * The Apache Software License, Version 1.1
0020: *
0021: * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
0022: * reserved.
0023: *
0024: * Redistribution and use in source and binary forms, with or without
0025: * modification, are permitted provided that the following conditions
0026: * are met:
0027: *
0028: * 1. Redistributions of source code must retain the above copyright
0029: * notice, this list of conditions and the following disclaimer.
0030: *
0031: * 2. Redistributions in binary form must reproduce the above copyright
0032: * notice, this list of conditions and the following disclaimer in
0033: * the documentation and/or other materials provided with the
0034: * distribution.
0035: *
0036: * 3. The end-user documentation included with the redistribution, if
0037: * any, must include the following acknowlegement:
0038: * "This product includes software developed by the
0039: * Apache Software Foundation (http://www.apache.org/)."
0040: * Alternately, this acknowlegement may appear in the software itself,
0041: * if and wherever such third-party acknowlegements normally appear.
0042: *
0043: * 4. The names "The Jakarta Project", "Commons", and "Apache Software
0044: * Foundation" must not be used to endorse or promote products derived
0045: * from this software without prior written permission. For written
0046: * permission, please contact apache@apache.org.
0047: *
0048: * 5. Products derived from this software may not be called "Apache"
0049: * nor may "Apache" appear in their names without prior written
0050: * permission of the Apache Group.
0051: *
0052: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0053: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0054: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0055: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0056: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0057: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0058: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0059: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0060: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0061: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0062: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0063: * SUCH DAMAGE.
0064: * ====================================================================
0065: *
0066: * This software consists of voluntary contributions made by many
0067: * individuals on behalf of the Apache Software Foundation. For more
0068: * information on the Apache Software Foundation, please see
0069: * <http://www.apache.org/>.
0070: *
0071: */
0072:
0073: package org.logicalcobwebs.proxool.util;
0074:
0075: import java.util.ArrayList;
0076: import java.util.Collection;
0077: import java.util.ConcurrentModificationException;
0078: import java.util.Iterator;
0079: import java.util.List;
0080: import java.util.ListIterator;
0081:
0082: /**
0083: * <p>A customized implementation of <code>java.util.ArrayList</code> designed
0084: * to operate in a multithreaded environment where the large majority of
0085: * method calls are read-only, instead of structural changes. When operating
0086: * in "fast" mode, read calls are non-synchronized and write calls perform the
0087: * following steps:</p>
0088: * <ul>
0089: * <li>Clone the existing collection
0090: * <li>Perform the modification on the clone
0091: * <li>Replace the existing collection with the (modified) clone
0092: * </ul>
0093: * <p>When first created, objects of this class default to "slow" mode, where
0094: * all accesses of any type are synchronized but no cloning takes place. This
0095: * is appropriate for initially populating the collection, followed by a switch
0096: * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
0097: * is complete.</p>
0098: *
0099: * <p><strong>NOTE</strong>: If you are creating and accessing an
0100: * <code>ArrayList</code> only within a single thread, you should use
0101: * <code>java.util.ArrayList</code> directly (with no synchronization), for
0102: * maximum performance.</p>
0103: *
0104: * <P><strong>NOTE</strong>: <I>This class is not cross-platform.
0105: * Using it may cause unexpected failures on some architectures.</I>
0106: * It suffers from the same problems as the double-checked locking idiom.
0107: * In particular, the instruction that clones the internal collection and the
0108: * instruction that sets the internal reference to the clone can be executed
0109: * or perceived out-of-order. This means that any read operation might fail
0110: * unexpectedly, as it may be reading the state of the internal collection
0111: * before the internal collection is fully formed.
0112: * For more information on the double-checked locking idiom, see the
0113: * <A Href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
0114: * Double-Checked Locking Idiom Is Broken Declartion</A>.</P>
0115: *
0116: * @since Proxool 0.6
0117: * @author Craig R. McClanahan
0118: * @author $Author: billhorsman $ (current maintainer)
0119: * @version $Revision: 1.4 $ $Date: 2003/03/10 23:43:18 $
0120: */
0121:
0122: public class FastArrayList extends ArrayList {
0123:
0124: // ----------------------------------------------------------- Constructors
0125:
0126: /**
0127: * Construct a an empty list.
0128: */
0129: public FastArrayList() {
0130:
0131: super ();
0132: this .list = new ArrayList();
0133:
0134: }
0135:
0136: /**
0137: * Construct an empty list with the specified capacity.
0138: *
0139: * @param capacity The initial capacity of the empty list
0140: */
0141: public FastArrayList(int capacity) {
0142:
0143: super ();
0144: this .list = new ArrayList(capacity);
0145:
0146: }
0147:
0148: /**
0149: * Construct a list containing the elements of the specified collection,
0150: * in the order they are returned by the collection's iterator.
0151: *
0152: * @param collection The collection whose elements initialize the contents
0153: * of this list
0154: */
0155: public FastArrayList(Collection collection) {
0156:
0157: super ();
0158: this .list = new ArrayList(collection);
0159:
0160: }
0161:
0162: // ----------------------------------------------------- Instance Variables
0163:
0164: /**
0165: * The underlying list we are managing.
0166: */
0167: private ArrayList list = null;
0168:
0169: // ------------------------------------------------------------- Properties
0170:
0171: /**
0172: * Are we operating in "fast" mode?
0173: */
0174: private boolean fast = false;
0175:
0176: /**
0177: * Returns true if this list is operating in fast mode.
0178: *
0179: * @return true if this list is operating in fast mode
0180: */
0181: public boolean getFast() {
0182: return (this .fast);
0183: }
0184:
0185: /**
0186: * Sets whether this list will operate in fast mode.
0187: *
0188: * @param fast true if the list should operate in fast mode
0189: */
0190: public void setFast(boolean fast) {
0191: this .fast = fast;
0192: }
0193:
0194: // --------------------------------------------------------- Public Methods
0195:
0196: /**
0197: * Appends the specified element to the end of this list.
0198: *
0199: * @param element The element to be appended
0200: */
0201: public boolean add(Object element) {
0202:
0203: if (fast) {
0204: synchronized (this ) {
0205: ArrayList temp = (ArrayList) list.clone();
0206: boolean result = temp.add(element);
0207: list = temp;
0208: return (result);
0209: }
0210: } else {
0211: synchronized (list) {
0212: return (list.add(element));
0213: }
0214: }
0215:
0216: }
0217:
0218: /**
0219: * Insert the specified element at the specified position in this list,
0220: * and shift all remaining elements up one position.
0221: *
0222: * @param index Index at which to insert this element
0223: * @param element The element to be inserted
0224: *
0225: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0226: */
0227: public void add(int index, Object element) {
0228:
0229: if (fast) {
0230: synchronized (this ) {
0231: ArrayList temp = (ArrayList) list.clone();
0232: temp.add(index, element);
0233: list = temp;
0234: }
0235: } else {
0236: synchronized (list) {
0237: list.add(index, element);
0238: }
0239: }
0240:
0241: }
0242:
0243: /**
0244: * Append all of the elements in the specified Collection to the end
0245: * of this list, in the order that they are returned by the specified
0246: * Collection's Iterator.
0247: *
0248: * @param collection The collection to be appended
0249: */
0250: public boolean addAll(Collection collection) {
0251:
0252: if (fast) {
0253: synchronized (this ) {
0254: ArrayList temp = (ArrayList) list.clone();
0255: boolean result = temp.addAll(collection);
0256: list = temp;
0257: return (result);
0258: }
0259: } else {
0260: synchronized (list) {
0261: return (list.addAll(collection));
0262: }
0263: }
0264:
0265: }
0266:
0267: /**
0268: * Insert all of the elements in the specified Collection at the specified
0269: * position in this list, and shift any previous elements upwards as
0270: * needed.
0271: *
0272: * @param index Index at which insertion takes place
0273: * @param collection The collection to be added
0274: *
0275: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0276: */
0277: public boolean addAll(int index, Collection collection) {
0278:
0279: if (fast) {
0280: synchronized (this ) {
0281: ArrayList temp = (ArrayList) list.clone();
0282: boolean result = temp.addAll(index, collection);
0283: list = temp;
0284: return (result);
0285: }
0286: } else {
0287: synchronized (list) {
0288: return (list.addAll(index, collection));
0289: }
0290: }
0291:
0292: }
0293:
0294: /**
0295: * Remove all of the elements from this list. The list will be empty
0296: * after this call returns.
0297: *
0298: * @exception java.lang.UnsupportedOperationException if <code>clear()</code>
0299: * is not supported by this list
0300: */
0301: public void clear() {
0302:
0303: if (fast) {
0304: synchronized (this ) {
0305: ArrayList temp = (ArrayList) list.clone();
0306: temp.clear();
0307: list = temp;
0308: }
0309: } else {
0310: synchronized (list) {
0311: list.clear();
0312: }
0313: }
0314:
0315: }
0316:
0317: /**
0318: * Return a shallow copy of this <code>FastArrayList</code> instance.
0319: * The elements themselves are not copied.
0320: */
0321: public Object clone() {
0322:
0323: FastArrayList results = null;
0324: if (fast) {
0325: results = new FastArrayList(list);
0326: } else {
0327: synchronized (list) {
0328: results = new FastArrayList(list);
0329: }
0330: }
0331: results.setFast(getFast());
0332: return (results);
0333:
0334: }
0335:
0336: /**
0337: * Return <code>true</code> if this list contains the specified element.
0338: *
0339: * @param element The element to test for
0340: */
0341: public boolean contains(Object element) {
0342:
0343: if (fast) {
0344: return (list.contains(element));
0345: } else {
0346: synchronized (list) {
0347: return (list.contains(element));
0348: }
0349: }
0350:
0351: }
0352:
0353: /**
0354: * Return <code>true</code> if this list contains all of the elements
0355: * in the specified Collection.
0356: *
0357: * @param collection Collection whose elements are to be checked
0358: */
0359: public boolean containsAll(Collection collection) {
0360:
0361: if (fast) {
0362: return (list.containsAll(collection));
0363: } else {
0364: synchronized (list) {
0365: return (list.containsAll(collection));
0366: }
0367: }
0368:
0369: }
0370:
0371: /**
0372: * Increase the capacity of this <code>ArrayList</code> instance, if
0373: * necessary, to ensure that it can hold at least the number of elements
0374: * specified by the minimum capacity argument.
0375: *
0376: * @param capacity The new minimum capacity
0377: */
0378: public void ensureCapacity(int capacity) {
0379:
0380: if (fast) {
0381: synchronized (this ) {
0382: ArrayList temp = (ArrayList) list.clone();
0383: temp.ensureCapacity(capacity);
0384: list = temp;
0385: }
0386: } else {
0387: synchronized (list) {
0388: list.ensureCapacity(capacity);
0389: }
0390: }
0391:
0392: }
0393:
0394: /**
0395: * Compare the specified object with this list for equality. This
0396: * implementation uses exactly the code that is used to define the
0397: * list equals function in the documentation for the
0398: * <code>List.equals</code> method.
0399: *
0400: * @param o Object to be compared to this list
0401: */
0402: public boolean equals(Object o) {
0403:
0404: // Simple tests that require no synchronization
0405: if (o == this ) {
0406: return (true);
0407: } else if (!(o instanceof List)) {
0408: return (false);
0409: }
0410: List lo = (List) o;
0411:
0412: // Compare the sets of elements for equality
0413: if (fast) {
0414: ListIterator li1 = list.listIterator();
0415: ListIterator li2 = lo.listIterator();
0416: while (li1.hasNext() && li2.hasNext()) {
0417: Object o1 = li1.next();
0418: Object o2 = li2.next();
0419: if (!(o1 == null ? o2 == null : o1.equals(o2))) {
0420: return (false);
0421: }
0422: }
0423: return (!(li1.hasNext() || li2.hasNext()));
0424: } else {
0425: synchronized (list) {
0426: ListIterator li1 = list.listIterator();
0427: ListIterator li2 = lo.listIterator();
0428: while (li1.hasNext() && li2.hasNext()) {
0429: Object o1 = li1.next();
0430: Object o2 = li2.next();
0431: if (!(o1 == null ? o2 == null : o1.equals(o2))) {
0432: return (false);
0433: }
0434: }
0435: return (!(li1.hasNext() || li2.hasNext()));
0436: }
0437: }
0438:
0439: }
0440:
0441: /**
0442: * Return the element at the specified position in the list.
0443: *
0444: * @param index The index of the element to return
0445: *
0446: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0447: */
0448: public Object get(int index) {
0449:
0450: if (fast) {
0451: return (list.get(index));
0452: } else {
0453: synchronized (list) {
0454: return (list.get(index));
0455: }
0456: }
0457:
0458: }
0459:
0460: /**
0461: * Return the hash code value for this list. This implementation uses
0462: * exactly the code that is used to define the list hash function in the
0463: * documentation for the <code>List.hashCode</code> method.
0464: */
0465: public int hashCode() {
0466:
0467: if (fast) {
0468: int hashCode = 1;
0469: java.util.Iterator i = list.iterator();
0470: while (i.hasNext()) {
0471: Object o = i.next();
0472: hashCode = 31 * hashCode
0473: + (o == null ? 0 : o.hashCode());
0474: }
0475: return (hashCode);
0476: } else {
0477: synchronized (list) {
0478: int hashCode = 1;
0479: java.util.Iterator i = list.iterator();
0480: while (i.hasNext()) {
0481: Object o = i.next();
0482: hashCode = 31 * hashCode
0483: + (o == null ? 0 : o.hashCode());
0484: }
0485: return (hashCode);
0486: }
0487: }
0488:
0489: }
0490:
0491: /**
0492: * Search for the first occurrence of the given argument, testing
0493: * for equality using the <code>equals()</code> method, and return
0494: * the corresponding index, or -1 if the object is not found.
0495: *
0496: * @param element The element to search for
0497: */
0498: public int indexOf(Object element) {
0499:
0500: if (fast) {
0501: return (list.indexOf(element));
0502: } else {
0503: synchronized (list) {
0504: return (list.indexOf(element));
0505: }
0506: }
0507:
0508: }
0509:
0510: /**
0511: * Test if this list has no elements.
0512: */
0513: public boolean isEmpty() {
0514:
0515: if (fast) {
0516: return (list.isEmpty());
0517: } else {
0518: synchronized (list) {
0519: return (list.isEmpty());
0520: }
0521: }
0522:
0523: }
0524:
0525: /**
0526: * Return an iterator over the elements in this list in proper sequence.
0527: * <br><br>
0528: * <strong>IMPLEMENTATION NOTE</strong> - If the list is operating in fast
0529: * mode, an Iterator is returned, and a structural modification to the
0530: * list is made, then the Iterator will continue over the previous contents
0531: * of the list (at the time that the Iterator was created), rather than
0532: * failing due to concurrent modifications.
0533: */
0534: public Iterator iterator() {
0535: if (fast) {
0536: return new ListIter(0);
0537: } else {
0538: return list.iterator();
0539: }
0540: }
0541:
0542: /**
0543: * Search for the last occurrence of the given argument, testing
0544: * for equality using the <code>equals()</code> method, and return
0545: * the corresponding index, or -1 if the object is not found.
0546: *
0547: * @param element The element to search for
0548: */
0549: public int lastIndexOf(Object element) {
0550:
0551: if (fast) {
0552: return (list.lastIndexOf(element));
0553: } else {
0554: synchronized (list) {
0555: return (list.lastIndexOf(element));
0556: }
0557: }
0558:
0559: }
0560:
0561: /**
0562: * Return an iterator of the elements of this list, in proper sequence.
0563: * See the implementation note on <code>iterator()</code>.
0564: */
0565: public ListIterator listIterator() {
0566: if (fast) {
0567: return new ListIter(0);
0568: } else {
0569: return list.listIterator();
0570: }
0571: }
0572:
0573: /**
0574: * Return an iterator of the elements of this list, in proper sequence,
0575: * starting at the specified position.
0576: * See the implementation note on <code>iterator()</code>.
0577: *
0578: * @param index The starting position of the iterator to return
0579: *
0580: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0581: */
0582: public ListIterator listIterator(int index) {
0583: if (fast) {
0584: return new ListIter(index);
0585: } else {
0586: return list.listIterator(index);
0587: }
0588: }
0589:
0590: /**
0591: * Remove the element at the specified position in the list, and shift
0592: * any subsequent elements down one position.
0593: *
0594: * @param index Index of the element to be removed
0595: *
0596: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0597: */
0598: public Object remove(int index) {
0599:
0600: if (fast) {
0601: synchronized (this ) {
0602: ArrayList temp = (ArrayList) list.clone();
0603: Object result = temp.remove(index);
0604: list = temp;
0605: return (result);
0606: }
0607: } else {
0608: synchronized (list) {
0609: return (list.remove(index));
0610: }
0611: }
0612:
0613: }
0614:
0615: /**
0616: * Remove the first occurrence of the specified element from the list,
0617: * and shift any subsequent elements down one position.
0618: *
0619: * @param element Element to be removed
0620: */
0621: public boolean remove(Object element) {
0622:
0623: if (fast) {
0624: synchronized (this ) {
0625: ArrayList temp = (ArrayList) list.clone();
0626: boolean result = temp.remove(element);
0627: list = temp;
0628: return (result);
0629: }
0630: } else {
0631: synchronized (list) {
0632: return (list.remove(element));
0633: }
0634: }
0635:
0636: }
0637:
0638: /**
0639: * Remove from this collection all of its elements that are contained
0640: * in the specified collection.
0641: *
0642: * @param collection Collection containing elements to be removed
0643: *
0644: * @exception java.lang.UnsupportedOperationException if this optional operation
0645: * is not supported by this list
0646: */
0647: public boolean removeAll(Collection collection) {
0648:
0649: if (fast) {
0650: synchronized (this ) {
0651: ArrayList temp = (ArrayList) list.clone();
0652: boolean result = temp.removeAll(collection);
0653: list = temp;
0654: return (result);
0655: }
0656: } else {
0657: synchronized (list) {
0658: return (list.removeAll(collection));
0659: }
0660: }
0661:
0662: }
0663:
0664: /**
0665: * Remove from this collection all of its elements except those that are
0666: * contained in the specified collection.
0667: *
0668: * @param collection Collection containing elements to be retained
0669: *
0670: * @exception java.lang.UnsupportedOperationException if this optional operation
0671: * is not supported by this list
0672: */
0673: public boolean retainAll(Collection collection) {
0674:
0675: if (fast) {
0676: synchronized (this ) {
0677: ArrayList temp = (ArrayList) list.clone();
0678: boolean result = temp.retainAll(collection);
0679: list = temp;
0680: return (result);
0681: }
0682: } else {
0683: synchronized (list) {
0684: return (list.retainAll(collection));
0685: }
0686: }
0687:
0688: }
0689:
0690: /**
0691: * Replace the element at the specified position in this list with
0692: * the specified element. Returns the previous object at that position.
0693: * <br><br>
0694: * <strong>IMPLEMENTATION NOTE</strong> - This operation is specifically
0695: * documented to not be a structural change, so it is safe to be performed
0696: * without cloning.
0697: *
0698: * @param index Index of the element to replace
0699: * @param element The new element to be stored
0700: *
0701: * @exception java.lang.IndexOutOfBoundsException if the index is out of range
0702: */
0703: public Object set(int index, Object element) {
0704:
0705: if (fast) {
0706: return (list.set(index, element));
0707: } else {
0708: synchronized (list) {
0709: return (list.set(index, element));
0710: }
0711: }
0712:
0713: }
0714:
0715: /**
0716: * Return the number of elements in this list.
0717: */
0718: public int size() {
0719:
0720: if (fast) {
0721: return (list.size());
0722: } else {
0723: synchronized (list) {
0724: return (list.size());
0725: }
0726: }
0727:
0728: }
0729:
0730: /**
0731: * Return a view of the portion of this list between fromIndex
0732: * (inclusive) and toIndex (exclusive). The returned list is backed
0733: * by this list, so non-structural changes in the returned list are
0734: * reflected in this list. The returned list supports
0735: * all of the optional list operations supported by this list.
0736: *
0737: * @param fromIndex The starting index of the sublist view
0738: * @param toIndex The index after the end of the sublist view
0739: *
0740: * @exception java.lang.IndexOutOfBoundsException if an index is out of range
0741: */
0742: public List subList(int fromIndex, int toIndex) {
0743: if (fast) {
0744: return new SubList(fromIndex, toIndex);
0745: } else {
0746: return list.subList(fromIndex, toIndex);
0747: }
0748: }
0749:
0750: /**
0751: * Return an array containing all of the elements in this list in the
0752: * correct order.
0753: */
0754: public Object[] toArray() {
0755:
0756: if (fast) {
0757: return (list.toArray());
0758: } else {
0759: synchronized (list) {
0760: return (list.toArray());
0761: }
0762: }
0763:
0764: }
0765:
0766: /**
0767: * Return an array containing all of the elements in this list in the
0768: * correct order. The runtime type of the returned array is that of
0769: * the specified array. If the list fits in the specified array, it is
0770: * returned therein. Otherwise, a new array is allocated with the
0771: * runtime type of the specified array, and the size of this list.
0772: *
0773: * @param array Array defining the element type of the returned list
0774: *
0775: * @exception java.lang.ArrayStoreException if the runtime type of <code>array</code>
0776: * is not a supertype of the runtime type of every element in this list
0777: */
0778: public Object[] toArray(Object array[]) {
0779:
0780: if (fast) {
0781: return (list.toArray(array));
0782: } else {
0783: synchronized (list) {
0784: return (list.toArray(array));
0785: }
0786: }
0787:
0788: }
0789:
0790: /**
0791: * Return a String representation of this object.
0792: */
0793: public String toString() {
0794:
0795: StringBuffer sb = new StringBuffer("FastArrayList[");
0796: sb.append(list.toString());
0797: sb.append("]");
0798: return (sb.toString());
0799:
0800: }
0801:
0802: /**
0803: * Trim the capacity of this <code>ArrayList</code> instance to be the
0804: * list's current size. An application can use this operation to minimize
0805: * the storage of an <code>ArrayList</code> instance.
0806: */
0807: public void trimToSize() {
0808:
0809: if (fast) {
0810: synchronized (this ) {
0811: ArrayList temp = (ArrayList) list.clone();
0812: temp.trimToSize();
0813: list = temp;
0814: }
0815: } else {
0816: synchronized (list) {
0817: list.trimToSize();
0818: }
0819: }
0820:
0821: }
0822:
0823: private class SubList implements List {
0824:
0825: private int first;
0826: private int last;
0827: private List expected;
0828:
0829: public SubList(int first, int last) {
0830: this .first = first;
0831: this .last = last;
0832: this .expected = list;
0833: }
0834:
0835: private List get(List l) {
0836: if (list != expected) {
0837: throw new ConcurrentModificationException();
0838: }
0839: return l.subList(first, last);
0840: }
0841:
0842: public void clear() {
0843: if (fast) {
0844: synchronized (FastArrayList.this ) {
0845: ArrayList temp = (ArrayList) list.clone();
0846: get(temp).clear();
0847: last = first;
0848: list = temp;
0849: expected = temp;
0850: }
0851: } else {
0852: synchronized (list) {
0853: get(expected).clear();
0854: }
0855: }
0856: }
0857:
0858: public boolean remove(Object o) {
0859: if (fast) {
0860: synchronized (FastArrayList.this ) {
0861: ArrayList temp = (ArrayList) list.clone();
0862: boolean r = get(temp).remove(o);
0863: if (r) {
0864: last--;
0865: }
0866: list = temp;
0867: expected = temp;
0868: return r;
0869: }
0870: } else {
0871: synchronized (list) {
0872: return get(expected).remove(o);
0873: }
0874: }
0875: }
0876:
0877: public boolean removeAll(Collection o) {
0878: if (fast) {
0879: synchronized (FastArrayList.this ) {
0880: ArrayList temp = (ArrayList) list.clone();
0881: List sub = get(temp);
0882: boolean r = sub.removeAll(o);
0883: if (r) {
0884: last = first + sub.size();
0885: }
0886: list = temp;
0887: expected = temp;
0888: return r;
0889: }
0890: } else {
0891: synchronized (list) {
0892: return get(expected).removeAll(o);
0893: }
0894: }
0895: }
0896:
0897: public boolean retainAll(Collection o) {
0898: if (fast) {
0899: synchronized (FastArrayList.this ) {
0900: ArrayList temp = (ArrayList) list.clone();
0901: List sub = get(temp);
0902: boolean r = sub.retainAll(o);
0903: if (r) {
0904: last = first + sub.size();
0905: }
0906: list = temp;
0907: expected = temp;
0908: return r;
0909: }
0910: } else {
0911: synchronized (list) {
0912: return get(expected).retainAll(o);
0913: }
0914: }
0915: }
0916:
0917: public int size() {
0918: if (fast) {
0919: return get(expected).size();
0920: } else {
0921: synchronized (list) {
0922: return get(expected).size();
0923: }
0924: }
0925: }
0926:
0927: public boolean isEmpty() {
0928: if (fast) {
0929: return get(expected).isEmpty();
0930: } else {
0931: synchronized (list) {
0932: return get(expected).isEmpty();
0933: }
0934: }
0935: }
0936:
0937: public boolean contains(Object o) {
0938: if (fast) {
0939: return get(expected).contains(o);
0940: } else {
0941: synchronized (list) {
0942: return get(expected).contains(o);
0943: }
0944: }
0945: }
0946:
0947: public boolean containsAll(Collection o) {
0948: if (fast) {
0949: return get(expected).containsAll(o);
0950: } else {
0951: synchronized (list) {
0952: return get(expected).containsAll(o);
0953: }
0954: }
0955: }
0956:
0957: public Object[] toArray(Object[] o) {
0958: if (fast) {
0959: return get(expected).toArray(o);
0960: } else {
0961: synchronized (list) {
0962: return get(expected).toArray(o);
0963: }
0964: }
0965: }
0966:
0967: public Object[] toArray() {
0968: if (fast) {
0969: return get(expected).toArray();
0970: } else {
0971: synchronized (list) {
0972: return get(expected).toArray();
0973: }
0974: }
0975: }
0976:
0977: public boolean equals(Object o) {
0978: if (o == this ) {
0979: return true;
0980: }
0981: if (fast) {
0982: return get(expected).equals(o);
0983: } else {
0984: synchronized (list) {
0985: return get(expected).equals(o);
0986: }
0987: }
0988: }
0989:
0990: public int hashCode() {
0991: if (fast) {
0992: return get(expected).hashCode();
0993: } else {
0994: synchronized (list) {
0995: return get(expected).hashCode();
0996: }
0997: }
0998: }
0999:
1000: public boolean add(Object o) {
1001: if (fast) {
1002: synchronized (FastArrayList.this ) {
1003: ArrayList temp = (ArrayList) list.clone();
1004: boolean r = get(temp).add(o);
1005: if (r) {
1006: last++;
1007: }
1008: list = temp;
1009: expected = temp;
1010: return r;
1011: }
1012: } else {
1013: synchronized (list) {
1014: return get(expected).add(o);
1015: }
1016: }
1017: }
1018:
1019: public boolean addAll(Collection o) {
1020: if (fast) {
1021: synchronized (FastArrayList.this ) {
1022: ArrayList temp = (ArrayList) list.clone();
1023: boolean r = get(temp).addAll(o);
1024: if (r) {
1025: last += o.size();
1026: }
1027: list = temp;
1028: expected = temp;
1029: return r;
1030: }
1031: } else {
1032: synchronized (list) {
1033: return get(expected).addAll(o);
1034: }
1035: }
1036: }
1037:
1038: public void add(int i, Object o) {
1039: if (fast) {
1040: synchronized (FastArrayList.this ) {
1041: ArrayList temp = (ArrayList) list.clone();
1042: get(temp).add(i, o);
1043: last++;
1044: list = temp;
1045: expected = temp;
1046: }
1047: } else {
1048: synchronized (list) {
1049: get(expected).add(i, o);
1050: }
1051: }
1052: }
1053:
1054: public boolean addAll(int i, Collection o) {
1055: if (fast) {
1056: synchronized (FastArrayList.this ) {
1057: ArrayList temp = (ArrayList) list.clone();
1058: boolean r = get(temp).addAll(i, o);
1059: list = temp;
1060: if (r) {
1061: last += o.size();
1062: }
1063: expected = temp;
1064: return r;
1065: }
1066: } else {
1067: synchronized (list) {
1068: return get(expected).addAll(i, o);
1069: }
1070: }
1071: }
1072:
1073: public Object remove(int i) {
1074: if (fast) {
1075: synchronized (FastArrayList.this ) {
1076: ArrayList temp = (ArrayList) list.clone();
1077: Object o = get(temp).remove(i);
1078: last--;
1079: list = temp;
1080: expected = temp;
1081: return o;
1082: }
1083: } else {
1084: synchronized (list) {
1085: return get(expected).remove(i);
1086: }
1087: }
1088: }
1089:
1090: public Object set(int i, Object a) {
1091: if (fast) {
1092: synchronized (FastArrayList.this ) {
1093: ArrayList temp = (ArrayList) list.clone();
1094: Object o = get(temp).set(i, a);
1095: list = temp;
1096: expected = temp;
1097: return o;
1098: }
1099: } else {
1100: synchronized (list) {
1101: return get(expected).set(i, a);
1102: }
1103: }
1104: }
1105:
1106: public Iterator iterator() {
1107: return new SubListIter(0);
1108: }
1109:
1110: public ListIterator listIterator() {
1111: return new SubListIter(0);
1112: }
1113:
1114: public ListIterator listIterator(int i) {
1115: return new SubListIter(i);
1116: }
1117:
1118: public Object get(int i) {
1119: if (fast) {
1120: return get(expected).get(i);
1121: } else {
1122: synchronized (list) {
1123: return get(expected).get(i);
1124: }
1125: }
1126: }
1127:
1128: public int indexOf(Object o) {
1129: if (fast) {
1130: return get(expected).indexOf(o);
1131: } else {
1132: synchronized (list) {
1133: return get(expected).indexOf(o);
1134: }
1135: }
1136: }
1137:
1138: public int lastIndexOf(Object o) {
1139: if (fast) {
1140: return get(expected).lastIndexOf(o);
1141: } else {
1142: synchronized (list) {
1143: return get(expected).lastIndexOf(o);
1144: }
1145: }
1146: }
1147:
1148: public List subList(int f, int l) {
1149: if (list != expected) {
1150: throw new ConcurrentModificationException();
1151: }
1152: return new SubList(first + f, f + l);
1153: }
1154:
1155: private class SubListIter implements ListIterator {
1156:
1157: private List expected;
1158: private ListIterator iter;
1159: private int lastReturnedIndex = -1;
1160:
1161: public SubListIter(int i) {
1162: this .expected = list;
1163: this .iter = SubList.this .get(expected).listIterator(i);
1164: }
1165:
1166: private void checkMod() {
1167: if (list != expected) {
1168: throw new ConcurrentModificationException();
1169: }
1170: }
1171:
1172: List get() {
1173: return SubList.this .get(expected);
1174: }
1175:
1176: public boolean hasNext() {
1177: checkMod();
1178: return iter.hasNext();
1179: }
1180:
1181: public Object next() {
1182: checkMod();
1183: lastReturnedIndex = iter.nextIndex();
1184: return iter.next();
1185: }
1186:
1187: public boolean hasPrevious() {
1188: checkMod();
1189: return iter.hasPrevious();
1190: }
1191:
1192: public Object previous() {
1193: checkMod();
1194: lastReturnedIndex = iter.previousIndex();
1195: return iter.previous();
1196: }
1197:
1198: public int previousIndex() {
1199: checkMod();
1200: return iter.previousIndex();
1201: }
1202:
1203: public int nextIndex() {
1204: checkMod();
1205: return iter.nextIndex();
1206: }
1207:
1208: public void remove() {
1209: checkMod();
1210: if (lastReturnedIndex < 0) {
1211: throw new IllegalStateException();
1212: }
1213: get().remove(lastReturnedIndex);
1214: last--;
1215: expected = list;
1216: iter = get().listIterator(previousIndex());
1217: lastReturnedIndex = -1;
1218: }
1219:
1220: public void set(Object o) {
1221: checkMod();
1222: if (lastReturnedIndex < 0) {
1223: throw new IllegalStateException();
1224: }
1225: get().set(lastReturnedIndex, o);
1226: expected = list;
1227: iter = get().listIterator(previousIndex() + 1);
1228: }
1229:
1230: public void add(Object o) {
1231: checkMod();
1232: int i = nextIndex();
1233: get().add(i, o);
1234: last++;
1235: iter = get().listIterator(i + 1);
1236: lastReturnedIndex = 1;
1237: }
1238:
1239: }
1240:
1241: }
1242:
1243: private class ListIter implements ListIterator {
1244:
1245: private List expected;
1246: private ListIterator iter;
1247: private int lastReturnedIndex = -1;
1248:
1249: public ListIter(int i) {
1250: this .expected = list;
1251: this .iter = get().listIterator(i);
1252: }
1253:
1254: private void checkMod() {
1255: if (list != expected) {
1256: throw new ConcurrentModificationException();
1257: }
1258: }
1259:
1260: List get() {
1261: return expected;
1262: }
1263:
1264: public boolean hasNext() {
1265: checkMod();
1266: return iter.hasNext();
1267: }
1268:
1269: public Object next() {
1270: checkMod();
1271: lastReturnedIndex = iter.nextIndex();
1272: return iter.next();
1273: }
1274:
1275: public boolean hasPrevious() {
1276: checkMod();
1277: return iter.hasPrevious();
1278: }
1279:
1280: public Object previous() {
1281: checkMod();
1282: lastReturnedIndex = iter.previousIndex();
1283: return iter.previous();
1284: }
1285:
1286: public int previousIndex() {
1287: checkMod();
1288: return iter.previousIndex();
1289: }
1290:
1291: public int nextIndex() {
1292: checkMod();
1293: return iter.nextIndex();
1294: }
1295:
1296: public void remove() {
1297: checkMod();
1298: if (lastReturnedIndex < 0) {
1299: throw new IllegalStateException();
1300: }
1301: get().remove(lastReturnedIndex);
1302: expected = list;
1303: iter = get().listIterator(previousIndex());
1304: lastReturnedIndex = -1;
1305: }
1306:
1307: public void set(Object o) {
1308: checkMod();
1309: if (lastReturnedIndex < 0) {
1310: throw new IllegalStateException();
1311: }
1312: get().set(lastReturnedIndex, o);
1313: expected = list;
1314: iter = get().listIterator(previousIndex() + 1);
1315: }
1316:
1317: public void add(Object o) {
1318: checkMod();
1319: int i = nextIndex();
1320: get().add(i, o);
1321: iter = get().listIterator(i + 1);
1322: lastReturnedIndex = 1;
1323: }
1324:
1325: }
1326: }
1327:
1328: /*
1329: Revision history:
1330: $Log: FastArrayList.java,v $
1331: Revision 1.4 2003/03/10 23:43:18 billhorsman
1332: reapplied checkstyle that i'd inadvertently let
1333: IntelliJ change...
1334:
1335: Revision 1.3 2003/03/10 15:27:00 billhorsman
1336: refactoringn of concurrency stuff (and some import
1337: optimisation)
1338:
1339: Revision 1.2 2003/03/03 11:12:02 billhorsman
1340: fixed licence
1341:
1342: Revision 1.1 2003/02/07 01:40:34 chr32
1343: Ok. Now *really* moving in from main proxool package.
1344:
1345: Revision 1.4 2003/02/07 01:34:17 chr32
1346: Made class public.
1347:
1348: Revision 1.3 2003/02/07 01:33:31 chr32
1349: Moved in from main proxool package.
1350:
1351: Revision 1.2 2003/01/15 14:51:14 billhorsman
1352: checkstyle
1353:
1354: */
|