001    /*
002       @(#)ConcurrentList.java  0.4 08Jul03
003      
004       Copyright (c) 2003 Arno Formella and Jose B. Gonzalez Lopez.
005       All Rights Reserved.
006      
007       LGPL
008       
009     */
010    
011    /* a possible package location */
012    // package es.uvigo.ei.cd.java.util.concurrent;
013    
014    import java.util.*;
015    
016    /**
017       Implementation of a concurrent list, similar, although not identical,
018       to the <tt>List</tt> interface.
019    
020       Implements all list operations, and permits all elements
021       (including <tt>null</tt>) to be stored in the list; however,
022       still not supported operations (especially bulk operations)
023       cause an <tt>UnSupportedOperationException</tt>.
024       Note that the size of a ConcurrentList has a special semantics:
025       it is defined as the number of iterations, the executing threads
026       needs to traverse the list.
027       In addition to implementing the
028       <tt>List</tt> interface, the <tt>ConcurrentList</tt> class provides
029       uniformly named methods to <tt>access</tt>, <tt>insert</tt> and
030       <tt>remove</tt> an element at the beginning and end of the list.
031       These operations allow a concurrent list to be used as a stack,
032       queue, or double-ended queue (deque).<p>
033      
034       <b>Note that this implementation allows for concurrent operations
035       to take place.</b> Multiple threads
036       may access the same list concurrently, the list <i>need not to </i>
037       be synchronized externally. All available methods including iteration
038       can be performed concurrently, but please note the following special
039       semantics of concurrently manipulating a list.<p>
040      
041       All of the operations perform as could be expected for a doubly-linked
042       list. Operations that index into the list will traverse the list
043       from the begining to the end. Additionally to this linear iteration,
044       the indexing thread must compete for locks during the iteration,
045       which possibly makes such operations quite slow.<p>
046      
047       Semantics of manipulating a list concurrently:
048       <ul>
049       <li>
050         If a concurrent list is manipulated by only one thread at a time,
051         the list behaves exactly as expected from a normal linked list.
052       <li>
053         If a concurrent list is manipulated by more than one thread at a time,
054         there exists a sequential ordering of the operations such that 
055         the list behaves exactly as expected from a normal linked list when
056         the operations are performed in that sequential order by only one thread.
057       </ul>
058    
059       Invariants of the implementation:
060       <ul>
061       <li>
062         All locks on items are aquired in strict order in direction from the
063         beginning to the ending of the linked items in the list.
064         Hence, the concurrently operating threads cannot deadlock.
065       <li>
066         Each item holds the number of iterators that currently hold this item
067         as item being last returned.
068       <li>
069         After a remove operation the item to be removed is not part of the
070         list any more.
071       <li>
072         The list contains always two dummy items indicating the head and
073         tail of the list which are never visible from the outside.
074       </ul>
075    
076       Notes on the implementation:
077       <ul>
078       <li>
079         The concurrent list does not implement directly the list interface,
080         because there exists no counter reporting the current length (or
081         size) of the list. The necessary update of such a counter in each
082         operation that modifies the list would serialize the concurrent
083         accesses.
084       <li>
085         The access operations come in two flavors: the one which return
086         the elements held at the items in the list, these operations will
087         throw a NoSuchElementException whenever the operation cannot be
088         performed; and the one which return the items where the elements
089         are located, these operations return <tt>null</tt> whenever the operation
090         cannot be performed.
091       <li>
092         All inserting methods are based on the private <tt>addBefore()</tt> method.
093       <li>
094         All removing methods are based on the private <tt>remove()</tt> method.
095       <li>
096         Note that you <b>must</b> use the <tt>removeCurrent()</tt> method of
097         the iterator to remove the current item while iterating.
098         It is a severe bug to call the remove method of the list instead,
099         because it will deadlock.
100         The implementation can neither detect nor prevent this deadlock.
101         Special care must be taken not to call accidentally any
102         of the remove operations while maintaining the
103         iterator over the item to be removed.
104       <li>
105         Access operations with indices or elements cause NoSuchElementException
106         if the specified operation cannot be performed.
107         Access operations with items return null of the specified operation
108         cannot be performed.
109       </ul>
110    
111       Possible extensions:
112       <ul>
113       <li>
114         One might think of maintaining an identification of the list within
115         each item. This would allow to throw exceptions if someone tries
116         to remove an item not belonging to the list.
117       <li>
118         The bulk operations are still not implemented. Before implementing
119         them one might consider the design of appropriate ConcurrentCollection
120         classes and interfaces first.
121       <li>
122         One might think of adding a counting flag at each item which indicates
123         that the item is currently blocked (or reserved) by some thread.
124         Such a counting flag would help to implement <it>views</it> of
125         the list (such as intended by the SubList-method of the list interface).
126       <li>
127         One might build a class to allow any thread the initialization
128         of the list after which the list is accessed concurrently.
129       <li>
130         One might extent the iterator implementation with reverse iteration
131         operations.
132       </ul>
133    
134       Revisions:
135       <ul>
136       <li>
137         (0.4) update of the introductory comments
138       <li>
139         (0.3) (1) <b>bugfix:</b>
140         in removeCurrent() could be trapped in an infinite loop.
141         (2) some volatile modifier added where necessary.
142       <li>
143         (0.2) <b>bugfix:</b>
144         removeCurrent did not set deleted to true and did not set
145         references correctly ... silly bug.
146       </ul>
147    
148       @author  Arno Formella and José B. González López
149       @version 0.4, 08Jul03
150       @see     List
151     */
152    public class ConcurrentList implements Cloneable {
153      /*
154       TODO list:
155       - consider implementing java.io.Serializable
156       - consider implementing the bulk operations
157       - consider implementing the equals operation
158      */
159    
160      /**
161         There are two dummy items which mark the head and the tail
162         of this list.
163    
164         A user of this list will never have access to
165         these items. Two markers are needed to guarantee deadlock
166         free access in all operations: locks on items are always
167         aquired in strict order in direction from head to tail.
168       */
169      private volatile transient ConcurrentItem head=new ConcurrentItem();
170      /**
171         There are two dummy items which mark the head and the tail
172         of this list.
173    
174         A user of this list will never have access to
175         these items. Two markers are needed to guarantee deadlock
176         free access in all operations: locks on items are always
177         aquired in strict order in direction from head to tail.
178       */
179      private volatile transient ConcurrentItem tail=new ConcurrentItem();
180    
181      /**
182         Constructs an empty concurrent list.
183       */
184      public ConcurrentList() {
185        head.next=tail;
186        tail.previous=head;
187      }
188    
189      /**
190         Indicates whether this list is currently empty.
191        
192         @return true if list is currently empty.
193       */
194      public boolean isEmpty() {
195        /*
196           This list is empty if there is no first item.
197         */
198        return getFirstItem()==null;
199      }
200    
201      /**
202         Returns the first element in this list.
203        
204         @return the first element in this list.
205         @throws NoSuchElementException if this list is currently empty.
206       */
207      public Object getFirst() {
208        /*
209           The currently first element is the element of the
210           item following the head once the thread has access
211           to the head.
212         */
213        synchronized(head) {
214          /*
215            Throw exception if the list is encountered empty.
216           */
217          if(head.next==tail) throw new NoSuchElementException();
218          return head.next.element;
219        }
220      }
221    
222      /**
223         Returns the last element in this list.
224        
225         @return the last element in this list.
226         @throws NoSuchElementException if this list is currently empty.
227       */
228      public Object getLast() {
229        /*
230           Insist on trying to get the lock over the last item in the list (the
231           previous of the tail) until the item locked is really the last one
232           in the list and has not been marked as deleted.
233         */
234        while(true) {
235          ConcurrentItem last=tail.previous;
236          synchronized(last) {
237            if(last.next==tail && !last.deleted) {
238              /*
239                 If the encountered item turns out to be the head of the list,
240                 the list is empty, hence, throw exception.
241               */
242              if(last==head) throw new NoSuchElementException(); 
243              return last.element;
244            }
245          }
246        }
247      }
248    
249      /**
250         Returns the first item in this list.
251       
252         @return the first item in this list
253                 or null if this list is currently empty.
254       */
255      public ConcurrentItem getFirstItem() {
256        /*
257           The currently first item is the item following the head
258           once the thread has access to the head.
259         */
260        synchronized(head) {
261          /*
262            Return null if the list is encountered empty.
263           */
264          if(head.next==tail) return null;
265          return head.next;
266        }
267      }
268    
269      /**
270         Returns the last item in this list.
271        
272         @return the last item in this list
273                 or null if this list is currently empty.
274       */
275      public ConcurrentItem getLastItem()  {
276        /*
277           Insist on trying to get the lock over the last item in the list (the
278           previous of the tail) until the item locked is really the last one
279           in the list and has not been marked as deleted.
280         */
281        while(true) {
282          ConcurrentItem last=tail.previous;
283          synchronized(last) {
284            if(last.next==tail && !last.deleted) {
285              /*
286                 If the encountered item turns out to be the head of the list,
287                 the list is empty, hence, return null.
288               */
289              if(last==head) return null; 
290              return last;
291            }
292          }
293        }
294      }
295    
296      /**
297         Removes and returns the first element from this list.
298        
299         @return the first element from this list.
300         @throws NoSuchElementException if this list is currently empty.
301         @throws InterruptedException if the thread is interrupted while
302                 waiting for iterators releasing the first item.
303       */
304      public Object removeFirst() throws InterruptedException {
305        Object first;
306        /*
307           Aquire the locks over the head and its successor.
308         */
309        synchronized(head) {
310          synchronized(head.next) {
311            /*
312               Save the element of the first item (next of head) and
313               remove the first item.
314               Note that <tt>remove()</tt> will possibly throw the exceptions,
315               so we need not to take care of whether the first item
316               turns out to be the head.
317               Further, <tt>remove()</tt> needs only to acquire the third lock
318               over the successor of the first item (clearly, provided
319               the list was not encountered empty).
320             */ 
321            first=head.next.element;
322            remove(head.next);
323          }
324        }
325        return first;
326      }
327    
328      /**
329         Removes and returns the last element from this list.
330        
331         @return the last element from this list.
332         @throws NoSuchElementException if this list is currently empty.
333         @throws InterruptedException if the thread is interrupted while
334                 waiting for iterators releasing the last item.
335       */
336      public Object removeLast() throws InterruptedException {
337        ConcurrentItem lastItem;
338        ConcurrentItem previous;
339        /*
340           Insist on trying to get the lock over the last item in the list (the
341           previous of the tail) until the item locked is really the last one
342           in the list and has not been marked as deleted.
343         */
344        while(true) {
345          previous=tail.previous;
346          synchronized(previous) {
347            synchronized(tail) {
348              if(previous.next==tail && !previous.deleted) {
349                /*
350                   If the encountered item turns out to be the head of the list,
351                   the list is empty, hence, throw exception.
352                 */
353                if(previous==head) throw new NoSuchElementException();
354                lastItem=previous;
355                /*
356                   Note it would be a violation of the invariant
357                   (order of lock acquiring)
358                   if one would try to remove the item at this point.
359                 */
360                break;
361              }
362            }
363          }
364        }
365        /*
366           Save the element of the item that was encountered beforehand as
367           the last item and remove the item afterwards. Note that the
368           item that was seen as last item in the previous loop is deleted,
369           however, when eventually all locks are aquired, other threads
370           might have inserted new items at the end of the list.
371         */
372        Object last=previous.element;
373        remove(lastItem);
374        return last;
375      }
376    
377      /**
378         Removes an item from this list.
379        
380         @param item the item to be removed.
381                Precondition: item is part of this list.
382         @throws NoSuchElementException of the this list is currently empty.
383         @throws InterruptedException if the thread is interrupted while
384                 waiting for iterators releasing the last item.
385       */
386      public void removeItem(ConcurrentItem item) throws InterruptedException {
387        remove(item);
388      }
389    
390      /**
391         Inserts the given element at the beginning of this list.
392         
393         @param element the element to be inserted at the beginning of this list.
394         @return the item that has been inserted.
395       */
396      public ConcurrentItem addFirst(Object element) {
397        /*
398           Aquire first the lock over the head, so at the time of
399           insertion, the element is put in front.
400         */
401        synchronized(head) {
402          return addBefore(element, head.next);
403        }
404      }
405    
406      /**
407         Appends the given element to the end of this list.
408         
409         @param element the element to be inserted at the end of this list.
410         @return the item that has been inserted.
411       */
412      public ConcurrentItem addLast(Object element) {
413        return addBefore(element, tail);
414      }
415    
416      /**
417         Appends the given element to the end of this list.
418         
419         @param element the element to be inserted at the end of this list.
420         @return always true.
421       */
422      public ConcurrentItem add(Object element) {
423        return addBefore(element, tail);
424      }
425    
426      /**
427         Inserts the given element to this list before of the given item.  
428         
429         @param element the element to be inserted.
430         @param item the item which the element is inserted before.
431                Precondition: item is part of this list.
432         @throws NoSuchElementException if the item has been deleted while waiting.
433       */
434      public ConcurrentItem addItem(Object element, ConcurrentItem item) {
435        return addBefore(element, item);
436      }
437    
438      /**
439         Makes this list the empty list.
440       */
441      public void clear() throws InterruptedException {
442        /*
443           Insist on trying to remove the first item unless the list is
444           encountered empty.
445         */
446        while(true) {
447          synchronized(head) {
448            if(head.next==tail) return;
449            remove(head.next);
450          }
451        }
452      }
453    
454      /**
455         Returns a ConcurrentIterator of the items or elements in this list
456         (in proper sequence), starting at the beginning of this list.
457        
458         The iterator is <i>fail-save</i>: if this list is structurally
459         modified at any time after the iterator is created, the iterator
460         will continue to the end of this list. Modifications behind the
461         current position of the iterator (i.e. in direction to the beginning)
462         will not be reflected during this iteration, modifications in
463         front of the current position of the iterator (i.e. in direction of
464         the ending) will be included in the on-going iteration.<p>
465         Note that you <b>must</b> use the removeCurrent method of the
466         iterator to remove the current item while iterating. It is a severe
467         bug to call the remove method of the list instead, because it will
468         deadlock. The implementation can neither detect nor prevent this
469         deadlock.
470        
471         @return an Iterator of the elements in this list (in proper
472                 sequence), starting at the beginning of this list.
473         @see Iterator
474       */
475      public ConcurrentIterator listIterator() {
476        return new ListItr();
477      }
478    
479      /**
480         Returns a ConcurrentIterator of the items or elements in this list
481         (in proper sequence), starting at the specified position in the list.
482    
483         The iterator is <i>fail-save</i>: if this list is structurally
484         modified at any time after the iterator is created, the iterator
485         will continue to the end of this list. Modifications behind the
486         current position of the iterator (i.e. in direction to the beginning)
487         will not be reflected during this iteration, modifications in
488         front of the current position of the iterator (i.e. in direction of
489         the ending) will be included in the on-going iteration.<p>
490         Note that you <b>must</b> use the <tt>removeCurrent()</tt> method of the
491         iterator to remove the current item while iterating. It is a severe
492         bug to call the <tt>remove()</tt> method of the list instead, because it will
493         deadlock. The implementation can neither detect nor prevent this
494         deadlock.
495        
496         @param index index of first element to be returned from the
497                iterator (by a call to <tt>next()</tt>).
498         @return a ConcurrentIterator of the items or elements in this list
499                 (in proper sequence), starting at the specified position
500                 in the list.
501         @throws IndexOutOfBoundsException if index is out of range.
502       */
503      public ConcurrentIterator listIterator(int index) {
504        return new ListItr(index);
505      }
506    
507      /**
508         Private implementation of the ConcurrentIterator.
509       */
510      private class ListItr implements ConcurrentIterator {
511    
512        /*
513           lastReturned holds the item that was last returned to the calling
514           thread. Hence, while constructing the iterator it is set to the
515           head indicating that still no item has been returned.
516         */    
517        private ConcurrentItem lastReturned=head;
518    
519        /**
520           Constructs an iterator of the items or elements in the list
521           (in proper sequence), starting at the beginning of the list.
522         */
523        ListItr() {
524          /*
525             Exclusive access is required to lastReturned (which is
526             actually the head), because the counter which counts the number
527             of iterators currently holding this item as lastReturned must
528             be incremented, so we can use a generic method to advance the
529             iterator, which always decrements the counter of the current item
530             and increments the counter of the next item.
531           */
532          synchronized(lastReturned) {
533            lastReturned.iteratorCounter++;
534          }
535        }
536    
537        /**
538           Constructs an iterator of the items or elements in the list
539           (in proper sequence), starting at the given position.
540    
541           @throws IndexOutOfBoundsException if index is out of range.
542         */
543        ListItr(int index) {
544          /*
545             Exclusive access is required to lastReturned (which is
546             actually the head), because the counter which counts the number
547             of iterators currently holding this item as lastReturned must
548             be incremented, so we can use a generic method to advance the
549             iterator, which always decrements the counter of the current item
550             and increments the counter of the next item.
551           */
552          /*
553            A negative index certainly is out of range.
554           */
555          if(index<0) throw new IndexOutOfBoundsException();
556          synchronized(lastReturned) {
557            lastReturned.iteratorCounter++;
558          }
559          /*
560            Iterate to the specified index.
561           */
562          while(nextItem()!=null) {
563            if(index==0) return;
564            index--;
565          }
566          /*
567            The list was not sufficiently long.
568           */
569          throw new IndexOutOfBoundsException();
570        }
571    
572        /**
573           Indicates whether there is another element after the current
574           position of the iterator.
575    
576           Note that the information returned by this method is not reliable
577           if other threads are concurrently manipulating this list.
578           Hence, subsequent calls to <tt>next()</tt> still might cause an
579           exception.
580    
581           @return true if an element is available, false otherwise.
582         */
583        public boolean hasNext() {
584          synchronized(lastReturned) {
585            return lastReturned.next==tail;
586          }
587        }
588    
589        /**
590           Returns the next element in the list.
591    
592           @return the next element in the list.
593           @throws NoSuchElementException if there are no more elements.
594         */
595        public Object next() {
596          Object element;
597          synchronized(lastReturned) {
598            /*
599              If the end of the list has already been reached earlier,
600              throw an exception.
601             */
602            if(lastReturned==tail) throw new NoSuchElementException();
603            synchronized(lastReturned.next) {
604              /*
605                The current and the next item are locked now. Decrement counter
606                of iterators in the current item and notify all threads possibly
607                waiting for the current element, if it is worthwhile.
608               */
609              lastReturned.iteratorCounter--;
610              if(lastReturned.iteratorCounter==0) lastReturned.notifyAll();
611              /*
612                If the end of the list is reached now, throw an exception.
613               */
614              lastReturned=lastReturned.next;
615              if(lastReturned==tail) throw new NoSuchElementException();
616              /*
617                Get the element to be returned and increment the counter of
618                iterators in the new current item.
619               */
620              element=lastReturned.element;
621              lastReturned.iteratorCounter++;
622            }
623          }
624          return element;
625        }
626      
627        /**
628           Returns the next item in the list.
629    
630           @return the next item in the list, or null if there are no more
631                   items.
632         */
633        public ConcurrentItem nextItem() {
634          ConcurrentItem item=null;
635          synchronized(lastReturned) {
636            /*
637              If the end of the list has already been reached earlier, return null.
638             */
639            if(lastReturned==tail) return null;
640            synchronized(lastReturned.next) {
641              /*
642                The current and the next item are locked now. Decrement counter
643                of iterators in the current item and notify all threads possibly
644                waiting for the current element, if it is worthwhile.
645               */
646              lastReturned.iteratorCounter--;
647              if(lastReturned.iteratorCounter==0) lastReturned.notifyAll();
648              lastReturned=lastReturned.next;
649              if(lastReturned!=tail) {
650                /*
651                  The end of the list has still not been reached.
652                  Get the item to be returned and increment the counter of
653                  iterators in the new current item.
654                 */
655                item=lastReturned;
656                lastReturned.iteratorCounter++;
657              }
658            }
659          }
660          return item;
661        }
662    
663        /**
664           Returns the next item and element in the list.
665    
666           Allows for an atomic access to an item of the list. If one uses
667           the separate forms of first accessing the item then accessing
668           the element, another thread might have changed the element of the
669           item in the mean while.
670           The method is only visible in the package, but there is a wrapper
671           method which uses an item to transfer the element to the caller.
672           The design with an array is easy to extent if more than
673           one element should be returned.
674    
675           @param elementArray the array will contain the element found,
676                  the array will be unchanged if there are no more elements.
677           @return the next item in the list, or null if there are no more
678                   elements.
679         */
680        ConcurrentItem nextItem(Object[] elementArray) {
681          ConcurrentItem item=null;
682          synchronized(lastReturned) {
683            /*
684              If the end of the list has already been reached earlier, return null.
685             */
686            if(lastReturned==tail) return null;
687            synchronized(lastReturned.next) {
688              /*
689                The current and the next item are locked now. Decrement counter
690                of iterators in the current item and notify all threads possibly
691                waiting for the current element, if it is worthwhile.
692               */
693              lastReturned.iteratorCounter--;
694              if(lastReturned.iteratorCounter==0) lastReturned.notifyAll();
695              lastReturned=lastReturned.next;
696              if(lastReturned!=tail) {
697                /*
698                  The end of the list has still not been reached.
699                  Get the element to be returned and increment the counter of
700                  iterators in the new current item.
701                 */
702                item=lastReturned;
703                elementArray[0]=item.element;
704                lastReturned.iteratorCounter++;
705              }
706            }
707          }
708          return item;
709        }
710    
711        /**
712           Returns the next item and element in the list.
713    
714           Allows for an atomic access to an item of the list. If one uses
715           the separate forms of first accessing the item then accessing
716           the element, another thread might have changed the element of the
717           item in the mean while.
718    
719           @param item the item where to place the corresponding element, item will
720                  be unchanged if there are no more elements.
721           @return the next item in the list, or null if there are no more
722                   elements.
723         */
724        public ConcurrentItem nextItem(ConcurrentItem item) {
725          Object[] elementArray = new Object[1];
726          ConcurrentItem next_item = nextItem(elementArray);
727          /*
728            change the item only if a valid item has been found
729           */
730          if(next_item!=null) item.element = elementArray[0];
731          return next_item;
732        }
733    
734        /**
735           The remove method declared by the iterator interface cannot be
736           overwritten directly, because a concurrent iterator might throw
737           an InterruptedException.
738    
739           Use removeCurrent instead.
740          
741           @see #removeCurrent
742         */
743        public void remove() {
744          throw new UnsupportedOperationException();
745        }
746    
747        /**
748           Removes the item currently held by the iterator.
749    
750           The iterator is placed to the previous item. The method can be
751           called several times without calling a <tt>next()</tt> method
752           as long as the iterator does not recover its initial state,
753           that is, being placed as after construction.
754    
755           @throws NoSuchElementException if there is no current item,
756                   i.e., if still none of the <tt>next()</tt> methods has
757                   been executed or if the iteration already has completed.
758           @throws InterruptedException if the thread is interrupted while
759                   waiting for iterators releasing the current item.
760         */ 
761        public void removeCurrent() throws InterruptedException { 
762          /*
763            Throw exception if there is nothing that can be removed.
764           */
765          if(lastReturned==tail || lastReturned==head)
766            throw new NoSuchElementException();
767          /*
768            Because we might need to wait for other iterators to release the
769            item to be removed, the flag is used to indicate that it is the first
770            time both locks (over the current and the previous item) have been
771            achieved, hence, the iteratorCounter still has to be decremented.
772           */
773          boolean firstTime=true;
774          /*
775            Once we have get hold on a valid predecessor of lastReturned, we
776            store it in toReturn, so we can return it once the removal took place.
777           */
778          ConcurrentItem toReturn=null;
779          /*
780            Insist on trying to get hold on the current item and its predecessor.
781            Because we must aquire the locks in strict order, the structure of
782            the loop is more complex.
783           */
784          while(true) {
785            ConcurrentItem previous=lastReturned.previous;
786            synchronized(previous) {
787              /*
788                If we still did not update the iteratorCounter,
789                check whether the previous one has not been deleted (we
790                need an item where to place lastReturned) and check as well
791                if we really got hold over the previous item of lastReturned.
792                If neither is the case, keep on trying.
793               */
794              if(firstTime && (previous.deleted || previous!=lastReturned.previous))
795                continue;
796              /*
797                We got hold on the previous undeleted item. Increment its
798                iteratorCounter indicating that it is in use and store it
799                so we can return it, once we have achieved the removal.
800               */
801              if(firstTime) {
802                previous.iteratorCounter++;
803                toReturn=previous;
804              }
805              /*
806                Get hold on the current item.
807               */
808              synchronized(lastReturned) {
809                /*
810                  It may happen that the item already has been removed by some
811                  other thread because we might be in a later iteration of the
812                  loop (and hence, the iteratorCounter was decremented already).
813                  If the item is already deleted, everything is fine so break;
814                 */
815                if(lastReturned.deleted) {
816                  lastReturned=toReturn;
817                  break;
818                }
819                /*
820                  Decrement iteratorCounter at most once, so check firstTime first.
821                 */
822                if(firstTime) lastReturned.iteratorCounter--;
823                /*
824                  Wait until all other iterators have released this item.
825                 */
826                if(lastReturned.iteratorCounter!=0) {
827                  try {
828                    /*
829                      we must wait on the lastReturned item
830                     */
831                    lastReturned.wait();
832                  }
833                  catch(InterruptedException e) {
834                    throw e;
835                  }
836                  /*
837                    Every next iteration will not be the first one any more.
838                   */
839                  firstTime=false;
840                  continue;
841                }
842                /*
843                  Aquire the third lock, the lock over the next item of the one
844                  to be removed.
845                 */
846                synchronized(lastReturned.next) {
847                  /*
848                    Perform the actual remove operation.
849                   */
850                  lastReturned.deleted=true;
851                  lastReturned.previous.next=lastReturned.next;
852                  lastReturned.next.previous=lastReturned.previous;
853                }
854                /*
855                  Notify all threads possibly waiting for the item just removed.
856                 */
857                lastReturned.notifyAll();
858                /*
859                  Adjust lastReturned to the predecessor and break.
860                 */
861                lastReturned=toReturn;
862                break;
863              }
864            }
865          }
866        }
867    
868        /**
869           Finishes an iteration.
870    
871           Because an iteration over a ConcurrentList needs to maintain some
872           state information, one should call this method whenever an iterator
873           is not used any more.
874           Once <tt>finish()</tt> has been called, the state of the iteration is
875           the same as if one had iterated to the end of the list.
876           If this advice is not followed, other threads might get blocked
877           until the garbage collector finalizes the iterator.
878         */
879        public void finish() {
880          synchronized(lastReturned) {
881            if(lastReturned!=tail) {
882              /*
883                Decrement the iteration counter, if worthwhile, notify all
884                threads waiting on the item, and finally, advance directly
885                to the tail.
886               */
887              lastReturned.iteratorCounter--;
888              if(lastReturned.iteratorCounter==0) lastReturned.notifyAll();
889              lastReturned=tail;
890            }
891          }
892        }
893    
894        /**
895           Adjusts the iterator counter and notifies waiting threads if
896           an iterator goes out of scope and <tt>finish()</tt> has not been
897           called appropriately.
898    
899           @throws Throwable whatever might be risen by the garbage collector.
900         */
901        protected void finalize() throws Throwable {
902          try {
903            synchronized(lastReturned) {
904              /*
905                An iteration has finished if the lastReturned item is set at
906                the tail.
907               */
908              if(lastReturned!=tail) {
909                /*
910                  Decrement the iteration counter, if worthwhile, notify all
911                  threads waiting on the item.
912                 */
913                lastReturned.iteratorCounter--;
914                if(lastReturned.iteratorCounter==0) lastReturned.notifyAll();
915              }
916            }
917          }
918          finally {
919            super.finalize();
920          }
921        }
922      }
923    
924      /**
925         Basic method to insert an item into this list.
926    
927         @param element the element to be inserted
928         @param item the item in front of which the element is to be inserted.
929                Precondition: item is part of the list.
930         @return the item that has been inserted.
931         @throws NoSuchElementException if the item in front of which the element
932            has to be inserted has been removed from this list while the thread
933            is waiting for the necessary locks.
934       */
935      private ConcurrentItem addBefore(Object element, ConcurrentItem item) {
936        /*
937          Insist on trying to lock the two consecutive items in the list.
938         */
939        while(true) {
940          ConcurrentItem previous=item.previous;
941          synchronized(previous) {      
942            synchronized(item) {  
943              /*
944                If the item in front of which we want to insert has been deleted
945                in the mean while, throw exception.
946               */
947              if(item.deleted) throw new NoSuchElementException();
948              /*
949                Check whether the two items are consecutive, if not: insist,
950                else insert a new item containing the element.
951               */
952              if(item.previous==previous) {
953                ConcurrentItem newItem=new ConcurrentItem(element, item, previous);
954                newItem.previous.next=newItem;
955                newItem.next.previous=newItem;
956                return newItem;
957              }
958            }
959          }
960        }
961      }
962    
963      /**
964         Basic method to remove an item from this list.
965    
966         @param  item the item to be removed.
967                 Precondition: item is part of this list.
968         @throws InterruptedException if the thread is interrupted while
969                 waiting for iterators releasing the item.
970         @throws NoSuchElementException if this list is empty.
971       */
972      private void remove(ConcurrentItem item) throws InterruptedException {
973        /*
974          Throw exception if the item cannot be removed.
975         */
976        if(item==head || item==tail) throw new NoSuchElementException();
977        /*
978          Insist on trying to lock the three consecutive items in the list.
979         */
980        while(true) {
981          ConcurrentItem previous=item.previous;
982          synchronized(previous) {
983            synchronized(item) {
984              /*
985                If the item was deleted by another thread, nothing must be done
986                any more.
987               */
988              if(item.deleted) break;
989              /*
990                If we did not lock the predecessor we need to continue (some other
991                thread might have inserted an item in the mean while).
992               */
993              if(item.previous!=previous) continue;
994              /*
995                Wait for the iterators to release the item to be removed.
996               */
997              if(item.iteratorCounter > 0) {
998                try {
999                  /*
1000                    We must wait on the item.
1001                   */
1002                  item.wait();
1003                }
1004                catch(InterruptedException ex) {
1005                  throw ex;
1006                }
1007                /*
1008                  Try to get the locks again.
1009                 */
1010                continue;
1011              }
1012              /*
1013                Get the third lock, remove the item, and done.
1014               */
1015              synchronized(item.next) {          
1016                item.deleted=true;
1017                item.previous.next=item.next;
1018                item.next.previous=item.previous;
1019                break;
1020              }
1021            }
1022          }
1023        }
1024      }
1025    
1026      /**
1027         Clones this list as currently seen by an iterator constructed for the
1028         thread.
1029    
1030         Note that due to the concurrent nature of a ConcurrentList the
1031         resulting clone might be a list that never existed exactly like this
1032         during the execution of the program.
1033         However, if the list is not modified during cloning, the clone
1034         is an exact copy.
1035    
1036         @return A new ConcurrentList containing all elements as seen
1037                 by the executing thread during the copy iteration.
1038       */
1039      protected Object clone() throws CloneNotSupportedException {
1040        /*
1041          Construct a new iterator and collect all items in the list as seen
1042          by this iterator.
1043         */
1044        ConcurrentList newList=new ConcurrentList();
1045        ListItr iterator=new ListItr();
1046        /*
1047          iterate over the list and add the element to a new list
1048         */
1049        Object[] elementArray=new Object[1];
1050        while(iterator.nextItem(elementArray)!=null)
1051          newList.addLast(elementArray[0]);
1052        return newList;
1053      }
1054    
1055      /**
1056         Returns the element at the specified position in this list.
1057    
1058         Note that the method iterates from the beginning of this list,
1059         hence the operation might be quite slow.
1060    
1061         @param index the index of the element to be returned.
1062         @return the object at the position specified by index.
1063         @throws IndexOutOfBoundsException if the specified index is out of range.
1064       */
1065      public Object get(int index) {
1066        /*
1067          A negative index certainly is out of range.
1068         */
1069        if(index<0) throw new IndexOutOfBoundsException();
1070        ListItr iterator=new ListItr();
1071        int counter=0;
1072        /*
1073          Step over the list unless the appropriate index has been reached or
1074          no more elements are available.
1075         */
1076        Object[] elementArray=new Object[1];
1077        while(iterator.nextItem(elementArray)!=null) {
1078          if(counter==index) {
1079            /*
1080              Finish the iteration because the iterator will go out of scope.
1081             */
1082            iterator.finish();
1083            return elementArray[0];
1084          }
1085          counter++;
1086        }
1087        /*
1088          The list was encountered shorter than necessary.
1089         */
1090        throw new IndexOutOfBoundsException();
1091      }
1092    
1093      /**
1094         Returns the item at the specified position in this list.
1095    
1096         Note that the method iterates from the beginning of this list,
1097         hence the operation might be quite slow.
1098    
1099         @param index the index of the item to be returned.
1100         @return the item at the position specified by index or null
1101                 if no such item exists.
1102       */
1103      public ConcurrentItem getItem(int index) {
1104        /*
1105          A negative index certainly is out of range.
1106         */
1107        if(index<0) return null;
1108        ListItr iterator=new ListItr();
1109        ConcurrentItem item;
1110        int counter=0;
1111        /*
1112          Step over the list unless the appropriate index has been reached or
1113          no more items are available.
1114         */
1115        while((item=iterator.nextItem())!=null) {
1116          if(counter==index) {
1117            /*
1118              Finish the iteration because the iterator will go out of scope.
1119             */
1120            iterator.finish();
1121            return item;
1122          }
1123          counter++;
1124        }
1125        /*
1126          The list was encountered shorter than necessary.
1127         */
1128        return null;
1129      }
1130    
1131      /**
1132         Returns the item at the specified position in this list and
1133         fills atomicly the array with the element encountered.
1134    
1135         The method is only visible in the package, but there is a wrapper
1136         method which uses an item to transfer the element to the caller.
1137         The design with an array is easy to extent if more than
1138         one element should be returned.
1139    
1140         Note that the method iterates from the beginning of this list,
1141         hence the operation might be quite slow.
1142    
1143         @param index the index of the item to be returned.
1144         @param elementArray, the array to hold the element found,
1145                the array will be unchanged if no appropriate item found
1146         @return the item at the position specified by index or null
1147                 if no such item exists.
1148       */
1149      ConcurrentItem getItem(int index, Object[] elementArray) {
1150        /*
1151          A negative index certainly is out of range.
1152         */
1153        if(index<0) return null;
1154        ListItr iterator=new ListItr();
1155        ConcurrentItem item;
1156        int counter=0;
1157        Object[] element_array=new Object[1];
1158        /*
1159          Step over the list unless the appropriate index has been reached or
1160          no more items are available.
1161         */
1162        while((item=iterator.nextItem(element_array))!=null) {
1163          if(counter==index) {
1164            /*
1165              Finish the iteration because the iterator will go out of scope.
1166             */
1167            iterator.finish();
1168            elementArray[0]=element_array[0];
1169            return item;
1170          }
1171          counter++;
1172        }
1173        /*
1174          The list was encountered shorter than necessary.
1175         */
1176        return null;
1177      }
1178    
1179      /**
1180         Returns the item at the specified position in this list and
1181         fills atomicly the parameter item with the element encountered.
1182    
1183         Allows for an atomic access to an item of the list. If one uses
1184         the separate forms of first accessing the item then accessing
1185         the element, another thread might have changed the element of the
1186         item in the mean while.
1187    
1188         Note that the method iterates from the beginning of this list,
1189         hence the operation might be quite slow.
1190    
1191         @param index the index of the item to be returned.
1192         @param item, the item to hold the element found,
1193                the item will be unchanged if no appropriate item found
1194         @return the item at the position specified by index or null
1195                 if no such item exists.
1196       */
1197      public ConcurrentItem getItem(int index, ConcurrentItem item) {
1198        Object[] element_array = new Object[1];
1199        ConcurrentItem get_item = getItem(index, element_array);
1200        /*
1201          change the item only if a valid item has been found
1202         */
1203        if(get_item!=null) item.element = element_array[0];
1204        return get_item;
1205      }
1206    
1207      /**
1208         Sets the element at the specified position.
1209    
1210         Note that the method iterates from the beginning of this list,
1211         hence the operation might be quite slow.
1212    
1213         @param index the index of the item to be returned.
1214         @param element the element used to replace
1215         @return the element found at the position specified by index.
1216         @throws IndexOutOfBoundsException if the specified index is out of range.
1217       */
1218      public Object set(int index, Object element) {
1219        /*
1220          A negative index certainly is out of range.
1221         */
1222        if(index<0) throw new IndexOutOfBoundsException();
1223        ListItr iterator=new ListItr();
1224        ConcurrentItem item;
1225        int counter=0;
1226        /*
1227          Iterate over the list and replace the element if the corresponding
1228          index is found.
1229         */
1230        while((item=iterator.nextItem())!=null) {
1231          if(counter==index) {
1232            /*
1233              Finish the iteration because the iterator will go out of scope.
1234             */
1235            iterator.finish();
1236            return item.setElement(element);
1237          }
1238          counter++;
1239        }
1240        /*
1241          The list was encountered shorter than necessary.
1242         */
1243        throw new IndexOutOfBoundsException();
1244      }
1245    
1246      /**
1247         Returns <tt>true</tt> if this list contains the specified element.
1248    
1249         Note that the method iterates from the beginning of this list,
1250         hence the operation might be quite slow.
1251    
1252         More formally, returns <tt>true</tt> if and only if this list contains
1253         at least one element <tt>e</tt> such that <tt>(element==null ? e==null
1254         : element.equals(e))</tt>.
1255        
1256         @param element element whose presence in this list is to be tested.
1257         @return <tt>true</tt> if this list contains the specified element.
1258       */
1259      public boolean contains(Object element) {
1260        return indexOf(element)!=-1;
1261      }
1262    
1263      /**
1264         Returns the index in this list of the first occurrence of the
1265         specified element, or -1 if this list does not contain the
1266         element.
1267    
1268         More formally, returns the lowest index i such that
1269         <tt>(element==null ? get(i)==null : element.equals(get(i)))</tt>,
1270         or -1 if there is no such index.
1271        
1272         @param element element to search for.
1273         @return the index in this list of the first occurrence of the
1274                 specified element, or -1 if the list does not contain the
1275                 element.
1276       */
1277      public int indexOf(Object element) {
1278        ListItr iterator=new ListItr();
1279        int index=0;
1280        Object[] elementArray=new Object[1];
1281        /*
1282          Distinguish the cases whether to compare the reference or whether
1283          to compare using the equals method of the object.
1284         */
1285        if(element==null) {
1286          /*
1287            Step over the list unless the appropriate element has been found or
1288            no more elements are available.
1289           */
1290          while(iterator.nextItem(elementArray)!=null) {
1291            if(elementArray[0]==null) {
1292              /*
1293                Finish the iteration because the iterator will go out of scope.
1294               */
1295              iterator.finish();
1296              return index;
1297            }
1298            index++;
1299          }
1300        }
1301        else {
1302          /*
1303            Step over the list unless the appropriate element has been found or
1304            no more elements are available.
1305           */
1306          while(iterator.nextItem(elementArray)!=null) {
1307            if(element.equals(elementArray[0])) {
1308              /*
1309                Finish the iteration because the iterator will go out of scope.
1310               */
1311              iterator.finish();
1312              return index;
1313            }
1314            index++;
1315          }
1316        }
1317        /*
1318          The element was not found.
1319         */
1320        return -1;
1321      }
1322    
1323      /**
1324         Inserts the specified element at the specified position in this list.
1325    
1326         Hence, shifts the element currently at that position (if any) and any
1327         subsequent elements to the right.
1328        
1329         @param index index at which the specified element is to be inserted.
1330         @param element element to be inserted.
1331         @throws IndexOutOfBoundsException if the specified index is out of range.
1332       */
1333      public void add(int index, Object element) {
1334        /*
1335          A negative index certainly is out of range.
1336         */
1337        if(index<0) throw new IndexOutOfBoundsException();
1338        ListItr iterator=new ListItr();
1339        ConcurrentItem item;
1340        /*
1341          Step over the list unless no more elements are available.
1342         */
1343        while((item=iterator.nextItem())!=null) {
1344          if(index==0) {
1345            /*
1346              Insert the item before the one corresponding to the index.
1347             */
1348            addBefore(element,item);
1349            /*
1350              Finish the iteration because the iterator will go out of scope.
1351             */
1352            iterator.finish();
1353            return;
1354          }
1355          index--;
1356        }
1357        /*
1358          The list was encountered shorter than necessary.
1359         */
1360        throw new IndexOutOfBoundsException();
1361      }
1362    
1363      /**
1364         Removes the element at the specified position in this list.
1365    
1366         hence, shifts any subsequent elements to the left.
1367         Returns the element that was removed from the list.
1368        
1369         @param index the index of the element to removed.
1370         @return the element previously at the specified position.
1371         @throws IndexOutOfBoundsException if the specified index is out of range.
1372         @throws InterruptedException if the thread is interrupted while
1373            waiting for iterators releasing the item
1374       */
1375      public Object remove(int index) throws InterruptedException {
1376        /*
1377          A negative index certainly is out of range.
1378         */
1379        if(index<0) throw new IndexOutOfBoundsException();
1380        ListItr iterator=new ListItr();
1381        Object[] elementArray=new Object[1];
1382        /*
1383          Step over the list unless no more elements are available.
1384         */
1385        while(iterator.nextItem(elementArray)!=null) {
1386          if(index==0) {
1387            /*
1388              Remove the item with the corresponding index.
1389             */
1390            iterator.removeCurrent();
1391            /*
1392              Finish the iteration because the iterator will go out of scope.
1393             */
1394            iterator.finish();
1395            return elementArray[0];
1396          }
1397          index--;
1398        }
1399        /*
1400          The list was encountered shorter than necessary.
1401         */
1402        throw new IndexOutOfBoundsException();
1403      }
1404    
1405      /**
1406         Removes the first occurrence of the specified element in this list.
1407    
1408         If the list does not contain the element, it is unchanged.
1409         More formally, removes the element with the lowest index <tt>i</tt>
1410         such that <tt>(element==null ? get(i)==null : element.equals(get(i)))</tt>
1411         (if such an element exists).
1412        
1413         @param element element to be removed from this list, if present.
1414         @return <tt>true</tt> if the list contained the specified element.
1415         @throws InterruptedException if the thread is interrupted while
1416            waiting for iterators releasing the item holding the element.
1417       */
1418      public boolean remove(Object element) throws InterruptedException {
1419        ListItr iterator=new ListItr();
1420        Object[] elementArray=new Object[1];
1421        /*
1422          Distinguish the cases whether to compare the reference or whether
1423          to compare using the equals method of the object.
1424         */
1425        if(element==null) {
1426          /*
1427            Step over the list unless no more elements are available.
1428           */
1429          while(iterator.nextItem(elementArray)!=null) {
1430            if(elementArray[0]==null) {
1431              /*
1432                Remove the item with the containg the element.
1433               */
1434              iterator.removeCurrent();
1435              /*
1436                Finish the iteration because the iterator will go out of scope.
1437               */
1438              iterator.finish();
1439              return true;
1440            }
1441          }
1442        }
1443        else {
1444          /*
1445            Step over the list unless no more elements are available.
1446           */
1447          while(iterator.nextItem(elementArray)!=null) {
1448            if(element.equals(elementArray[0])) {
1449              /*
1450                Remove the item with the containg the element.
1451               */
1452              iterator.removeCurrent();
1453              /*
1454                Finish the iteration because the iterator will go out of scope.
1455               */
1456              iterator.finish();
1457              return true;
1458            }
1459          }
1460        }
1461        /*
1462          The element was not found.
1463         */
1464        return false;
1465      }
1466    
1467      // Bulk Operations
1468    
1469      /**
1470         Appends all of the elements in the specified collection to the end of
1471         this list, in the order that they are returned by the specified
1472         collection's iterator (optional operation). 
1473    
1474         The behavior of this operation is unspecified if the specified
1475         collection is modified while the operation is in progress.
1476         (Note that this will occur if the specified collection is this list,
1477         and it's nonempty.)
1478        
1479         @param c collection whose elements are to be added to this list.
1480         @return <tt>true</tt> if this list changed as a result of the call.
1481         @throws UnsupportedOperationException if the <tt>addAll()</tt> method is
1482                 not supported by this list.
1483         @throws ClassCastException if the class of an element in the specified
1484               collection prevents it from being added to this list.
1485         @throws IllegalArgumentException if some aspect of an element in the
1486                 specified collection prevents it from being added to this
1487                 list.
1488         @see #add(Object)
1489       */
1490      public boolean addAll(Collection c) {
1491        throw new UnsupportedOperationException();
1492      }
1493    
1494      /**
1495         Inserts all of the elements in the specified collection into this
1496         list at the specified position (optional operation).
1497    
1498         Shifts the
1499         element currently at that position (if any) and any subsequent
1500         elements to the right (increases their indices).  The new elements
1501         will appear in this list in the order that they are returned by the
1502         specified collection's iterator.  The behavior of this operation is
1503         unspecified if the specified collection is modified while the
1504         operation is in progress.  (Note that this will occur if the specified
1505         collection is this list, and it's nonempty.)
1506        
1507         @param index index at which to insert first element from the specified
1508                    collection.
1509         @param c elements to be inserted into this list.
1510         @return <tt>true</tt> if this list changed as a result of the call.
1511         @throws UnsupportedOperationException if the <tt>addAll()</tt> method is
1512          not supported by this list.
1513         @throws ClassCastException if the class of one of elements of the
1514          specified collection prevents it from being added to this
1515          list.
1516         @throws IllegalArgumentException if some aspect of one of elements of
1517          the specified collection prevents it from being added to
1518          this list.
1519         @throws IndexOutOfBoundsException if the index is out of range.
1520       */
1521      public boolean addAll(int index, Collection c) {
1522        throw new UnsupportedOperationException();
1523      }
1524    
1525      /**
1526         Returns <tt>true</tt> if this list contains all of the elements of the
1527         specified collection.
1528        
1529         @param c collection to be checked for containment in this list.
1530         @return <tt>true</tt> if this list contains all of the elements of the
1531               specified collection.
1532         
1533         @see #contains(Object)
1534       */
1535      public boolean containsAll(Collection c) {
1536        throw new UnsupportedOperationException();
1537      }
1538    
1539      /**
1540         Removes from this list all the elements that are contained in the
1541         specified collection (optional operation).
1542        
1543         @param c collection that defines which elements will be removed from
1544                  this list.
1545         @return <tt>true</tt> if this list changed as a result of the call.
1546         @throws UnsupportedOperationException if the <tt>removeAll()</tt> method
1547           is not supported by this list.
1548         
1549         @see #remove(Object)
1550         @see #contains(Object)
1551       */
1552      public boolean removeAll(Collection c) {
1553        throw new UnsupportedOperationException();
1554      }
1555    
1556      /**
1557         Retains only the elements in this list that are contained in the
1558         specified collection (optional operation).
1559    
1560         In other words, removes
1561         from this list all the elements that are not contained in the specified
1562         collection.
1563        
1564         @param c collection that defines which elements this set will retain.
1565         @return <tt>true</tt> if this list changed as a result of the call.
1566         @throws UnsupportedOperationException if the <tt>retainAll()</tt> method
1567           is not supported by this list.
1568          
1569         @see #remove(Object)
1570         @see #contains(Object)
1571       */
1572      public boolean retainAll(Collection c) {
1573        throw new UnsupportedOperationException();
1574      }
1575    
1576      /**
1577         Compares the specified object with this list for equality.
1578    
1579         Returns
1580         <tt>true</tt> if and only if the specified object is also a list
1581         and all corresponding pairs of elements in
1582         the two lists are <i>equal</i>.  (Two elements <tt>e1</tt> and
1583         <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
1584         e1.equals(e2))</tt>.)  In other words, two lists are defined to be
1585         equal if they contain the same elements in the same order.  This
1586         definition ensures that the equals method works properly across
1587         different implementations of the <tt>List</tt> interface.
1588        
1589         @param obj the object to be compared for equality with this list.
1590         @return <tt>true</tt> if the specified object is equal to this list.
1591         @throws UnsupportedOperationException if the <tt>retainAll()</tt> method
1592           is not supported by this list.
1593       */
1594      public boolean equals(Object obj) {
1595        throw new UnsupportedOperationException();
1596      }
1597    
1598      /**
1599         Returns the hash code value for this list.
1600    
1601         The hash code of a list
1602         is defined to be the result of the following calculation:
1603         <pre>
1604           hashCode = 1;
1605           Iterator i = list.iterator();
1606           while (i.hasNext()) {
1607             Object obj = i.next();
1608             hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
1609          }
1610         </pre>
1611         This ensures that <tt>list1.equals(list2)</tt> implies that
1612         <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists,
1613         <tt>list1</tt> and <tt>list2</tt>, as required by the general
1614         contract of <tt>Object.hashCode</tt>.
1615        
1616         @return the hash code value for this list.
1617         @throws UnsupportedOperationException if the <tt>retainAll()</tt> method
1618           is not supported by this list.
1619    
1620         @see Object#hashCode()
1621         @see Object#equals(Object)
1622         @see #equals(Object)
1623       */
1624      public int hashCode() {
1625        throw new UnsupportedOperationException();
1626      }
1627    
1628      /**
1629         Returns the index in this list of the last occurrence of the specified
1630         element, or -1 if this list does not contain this element.
1631    
1632         More formally, returns the highest index <tt>i</tt> such that
1633         <tt>(element==null ? get(i)==null : element.equals(get(i)))</tt>,
1634         or -1 if there is no such index.
1635        
1636         @param element element to search for.
1637         @throws UnsupportedOperationException if the <tt>retainAll()</tt> method
1638           is not supported by this list.
1639         @return the index in this list of the last occurrence of the specified
1640               element, or -1 if this list does not contain this element.
1641       */
1642      public int lastIndexOf(Object element) {
1643        throw new UnsupportedOperationException();
1644      }
1645    
1646      /**
1647         The size of a ConcurrentList is defined as the number of
1648         iterations currently needed by this thread to traverse this list.
1649    
1650         Note that the information returned by this method is not reliable
1651         if other threads are concurrently manipulating this list.
1652         Hence, subsequent accesses to the list might see a different
1653         number of elements.
1654    
1655         Note that the operation might be quite slow, because the
1656         number of elements must be counted on the fly.
1657    
1658         @return the size of this list as currently seen by the thread.
1659       */
1660      public int size() {
1661        ListItr iterator=new ListItr();
1662        int index=0;
1663        while(iterator.nextItem()!=null) index++;
1664        return index;
1665      }
1666    
1667      /**
1668         Returns an array containing all elements of this list as seen
1669         currently by an iteration of the thread over this list.
1670    
1671         Note that due to the concurrent nature of a ConcurrentList the
1672         resulting array might be view of a list that never existed exactly
1673         like this during the execution of the program.
1674         However, if the list is not modified during the exection of this
1675         method, the array is an exact copy.
1676    
1677         @return an array containing all elements of this list.
1678       */
1679      public Object[] toArray() {
1680        /*
1681          In order to establish the necessary size of the array and
1682          to avoid that another thread manipulates the list while this
1683          thread tries to copy the elements, clone the list as seen by
1684          this thread.
1685         */
1686        ConcurrentList newList=null;
1687        try {
1688          newList=(ConcurrentList)this.clone();
1689        }
1690        catch(CloneNotSupportedException e) {
1691          // we know it's implemented
1692        }
1693        Object[] a=new Object[newList.size()];
1694        /*
1695          Return an array of the local copy of this list.
1696         */
1697        return newList.toArray(a);
1698      }
1699    
1700      /**
1701         Returns an array containing all elements of this list as seen
1702         currently by an iteration of the thread over this list.
1703    
1704         Note that due to the concurrent nature of a ConcurrentList the
1705         resulting array might be a view of the list that never existed exactly
1706         like this during the execution of the program.
1707         However, if the list is not modified during the exection of this
1708         method, the array is an exact copy.
1709    
1710         @param a the array to hold the elements of this list.
1711         @return an array containing all elements of this list.
1712         @throws IndexOutOfBoundsException if the array is not sufficiently
1713                 large to hold all elements
1714       */
1715      Object[] toArray(Object a[]) {
1716        /*
1717          Construct a new iterator and collect all items in the list as seen
1718          by this iterator.
1719         */
1720        ListItr iterator=new ListItr();
1721        Object[] elementArray=new Object[1];
1722        int index=0;
1723        /*
1724          iterate over the list and add the elements to the array
1725         */
1726        while(iterator.nextItem(elementArray)!=null)
1727          a[index++]=elementArray[0];
1728        return a;
1729      }
1730    
1731      /**
1732         Returns a view of the portion of this list between the specified
1733         <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
1734    
1735         (If
1736         <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
1737         empty.)  The returned list is backed by this list, so changes in the
1738         returned list are reflected in this list, and vice-versa.  The returned
1739         list supports all of the optional list operations supported by this
1740         list.<p>
1741        
1742         This method eliminates the need for explicit range operations (of
1743         the sort that commonly exist for arrays).   Any operation that expects
1744         a list can be used as a range operation by passing a subList view
1745         instead of a whole list.  For example, the following idiom
1746         removes a range of elements from a list:
1747         <pre>
1748             list.subList(from, to).clear();
1749         </pre>
1750         Similar idioms may be constructed for <tt>indexOf</tt> and
1751         <tt>lastIndexOf</tt>, and all of the algorithms in the
1752         <tt>Collections</tt> class can be applied to a subList.<p>
1753         
1754         The semantics of this list returned by this method become undefined if
1755         the backing list (i.e., this list) is <i>structurally modified</i> in
1756         any way other than via the returned list.  (Structural modifications are
1757         those that change the size of this list, or otherwise perturb it in such
1758         a fashion that iterations in progress may yield incorrect results.)
1759         
1760         @param fromIndex low endpoint (inclusive) of the subList.
1761         @param toIndex high endpoint (exclusive) of the subList.
1762         @return a view of the specified range within this list.
1763          
1764         @throws IndexOutOfBoundsException for an illegal endpoint index value
1765                 (fromIndex < 0 || toIndex > size || fromIndex > toIndex).
1766         @throws UnsupportedOperationException if the method
1767                 is not supported by this list.
1768       */
1769      public ConcurrentList subList(int fromIndex, int toIndex) {
1770        throw new UnsupportedOperationException();
1771      }
1772    }