You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2009/06/01 22:11:33 UTC

svn commit: r780808 - in /incubator/pivot/trunk: core/src/pivot/collections/ core/src/pivot/collections/adapter/ core/src/pivot/collections/concurrent/ core/src/pivot/util/ core/src/pivot/util/concurrent/ tools/src/pivot/tools/net/ web/src/pivot/web/ w...

Author: gbrown
Date: Mon Jun  1 20:11:32 2009
New Revision: 780808

URL: http://svn.apache.org/viewvc?rev=780808&view=rev
Log:
Fix design issue in synchronized collections (there was no way to release the listener the wrapper classes added to the source collection) - re-implement to fire events locally; eliminate SynchronizedListenerList and update classes that were using it to override add() and remove() themselves; eliminate poke() method from Stack class.

Removed:
    incubator/pivot/trunk/core/src/pivot/util/concurrent/SynchronizedListenerList.java
Modified:
    incubator/pivot/trunk/core/src/pivot/collections/ArrayQueue.java
    incubator/pivot/trunk/core/src/pivot/collections/ArrayStack.java
    incubator/pivot/trunk/core/src/pivot/collections/LinkedQueue.java
    incubator/pivot/trunk/core/src/pivot/collections/LinkedStack.java
    incubator/pivot/trunk/core/src/pivot/collections/List.java
    incubator/pivot/trunk/core/src/pivot/collections/Map.java
    incubator/pivot/trunk/core/src/pivot/collections/Queue.java
    incubator/pivot/trunk/core/src/pivot/collections/Set.java
    incubator/pivot/trunk/core/src/pivot/collections/Stack.java
    incubator/pivot/trunk/core/src/pivot/collections/adapter/ListAdapter.java
    incubator/pivot/trunk/core/src/pivot/collections/adapter/MapAdapter.java
    incubator/pivot/trunk/core/src/pivot/collections/adapter/SetAdapter.java
    incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedList.java
    incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedMap.java
    incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedQueue.java
    incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedSet.java
    incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedStack.java
    incubator/pivot/trunk/core/src/pivot/util/ListenerList.java
    incubator/pivot/trunk/tools/src/pivot/tools/net/Request.java
    incubator/pivot/trunk/web/src/pivot/web/Query.java
    incubator/pivot/trunk/wtk/src/pivot/wtk/Window.java

Modified: incubator/pivot/trunk/core/src/pivot/collections/ArrayQueue.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/ArrayQueue.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/ArrayQueue.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/ArrayQueue.java Mon Jun  1 20:11:32 2009
@@ -18,6 +18,8 @@
 
 import java.util.Comparator;
 
+import pivot.util.ListenerList;
+
 /**
  * Implementation of the {@link Queue} interface that is backed by an
  * array.
@@ -67,4 +69,8 @@
     public boolean isEmpty() {
         return (getLength() == 0);
     }
+
+    public ListenerList<QueueListener<T>> getQueueListeners() {
+        return queueListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/ArrayStack.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/ArrayStack.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/ArrayStack.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/ArrayStack.java Mon Jun  1 20:11:32 2009
@@ -18,6 +18,8 @@
 
 import java.util.Comparator;
 
+import pivot.util.ListenerList;
+
 /**
  * Implementation of the {@link Stack} interface that is backed by an
  * array.
@@ -64,16 +66,11 @@
         return item;
     }
 
-    public T poke(T item) {
-        int length = getLength();
-        if (length == 0) {
-            throw new IllegalStateException();
-        }
-
-        return update(length - 1, item);
-    }
-
     public boolean isEmpty() {
         return (getLength() == 0);
     }
+
+    public ListenerList<StackListener<T>> getStackListeners() {
+        return stackListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/LinkedQueue.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/LinkedQueue.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/LinkedQueue.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/LinkedQueue.java Mon Jun  1 20:11:32 2009
@@ -18,6 +18,8 @@
 
 import java.util.Comparator;
 
+import pivot.util.ListenerList;
+
 /**
  * Implementation of the {@link Queue} interface that is backed by a linked
  * list.
@@ -65,4 +67,8 @@
     public boolean isEmpty() {
         return (getLength() == 0);
     }
+
+    public ListenerList<QueueListener<T>> getQueueListeners() {
+        return queueListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/LinkedStack.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/LinkedStack.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/LinkedStack.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/LinkedStack.java Mon Jun  1 20:11:32 2009
@@ -18,6 +18,8 @@
 
 import java.util.Comparator;
 
+import pivot.util.ListenerList;
+
 /**
  * Implementation of the {@link Stack} interface that is backed by a linked
  * list.
@@ -62,16 +64,11 @@
         return item;
     }
 
-    public T poke(T item) {
-        int length = getLength();
-        if (length == 0) {
-            throw new IllegalStateException();
-        }
-
-        return update(length - 1, item);
-    }
-
     public boolean isEmpty() {
         return (getLength() == 0);
     }
+
+    public ListenerList<StackListener<T>> getStackListeners() {
+        return stackListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/List.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/List.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/List.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/List.java Mon Jun  1 20:11:32 2009
@@ -26,7 +26,7 @@
  */
 public interface List<T> extends Sequence<T>, Collection<T> {
     /**
-     * List listener list implementation.
+     * List listener list.
      *
      * @author gbrown
      */

Modified: incubator/pivot/trunk/core/src/pivot/collections/Map.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/Map.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/Map.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/Map.java Mon Jun  1 20:11:32 2009
@@ -27,7 +27,7 @@
  */
 public interface Map<K, V> extends Dictionary<K, V>, Collection<K> {
     /**
-     * Map listener list implementation.
+     * Map listener list.
      *
      * @author gbrown
      */

Modified: incubator/pivot/trunk/core/src/pivot/collections/Queue.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/Queue.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/Queue.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/Queue.java Mon Jun  1 20:11:32 2009
@@ -79,4 +79,9 @@
      * otherwise.
      */
     public boolean isEmpty();
+
+    /**
+     * Returns the queue listener list.
+     */
+    public ListenerList<QueueListener<T>> getQueueListeners();
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/Set.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/Set.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/Set.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/Set.java Mon Jun  1 20:11:32 2009
@@ -26,7 +26,7 @@
  */
 public interface Set<E> extends Group<E>, Collection<E> {
     /**
-     * Set listener list implementation.
+     * Set listener list.
      *
      * @author gbrown
      */

Modified: incubator/pivot/trunk/core/src/pivot/collections/Stack.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/Stack.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/Stack.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/Stack.java Mon Jun  1 20:11:32 2009
@@ -72,14 +72,6 @@
     public T peek();
 
     /**
-     * Replaces the item on top of the stack.
-     *
-     * @throws IllegalStateException
-     * If the stack contains no items.
-     */
-    public T poke(T item);
-
-    /**
      * Tests the emptiness of the stack.
      *
      * @return
@@ -87,4 +79,9 @@
      * otherwise.
      */
     public boolean isEmpty();
+
+    /**
+     * Returns the stack listener list.
+     */
+    public ListenerList<StackListener<T>> getStackListeners();
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/adapter/ListAdapter.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/adapter/ListAdapter.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/adapter/ListAdapter.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/adapter/ListAdapter.java Mon Jun  1 20:11:32 2009
@@ -85,17 +85,19 @@
         }
 
         T previousItem = list.get(index);
-        list.set(index, item);
-        listListeners.itemUpdated(this, index, previousItem);
+
+        if (previousItem != item) {
+            list.set(index, item);
+            listListeners.itemUpdated(this, index, previousItem);
+        }
 
         return previousItem;
     }
 
     public int remove(T item) {
         int index = indexOf(item);
-
         if (index == -1) {
-            throw new IllegalArgumentException("item is not an element of this list.");
+            throw new IllegalArgumentException();
         }
 
         remove(index, 1);
@@ -112,20 +114,24 @@
         } catch(InstantiationException exception) {
         }
 
-        for (int i = count - 1; i >= 0; i--) {
-            removedList.add(0, list.remove(index + i));
-        }
-
-        // Fire event
         List<T> removed = new ListAdapter<T>(removedList);
-        listListeners.itemsRemoved(this, index, removed);
+
+        if (count > 0) {
+            for (int i = count - 1; i >= 0; i--) {
+                removedList.add(0, list.remove(index + i));
+            }
+
+            listListeners.itemsRemoved(this, index, removed);
+        }
 
         return removed;
     }
 
     public void clear() {
-        list.clear();
-        listListeners.listCleared(this);
+        if (getLength() > 0) {
+            list.clear();
+            listListeners.listCleared(this);
+        }
     }
 
     public T get(int index) {

Modified: incubator/pivot/trunk/core/src/pivot/collections/adapter/MapAdapter.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/adapter/MapAdapter.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/adapter/MapAdapter.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/adapter/MapAdapter.java Mon Jun  1 20:11:32 2009
@@ -49,7 +49,7 @@
     }
 
     public V put(K key, V value) {
-        boolean update = map.containsKey(key);
+        boolean update = containsKey(key);
         V previousValue = map.put(key, value);
 
         if (update) {
@@ -65,7 +65,7 @@
     public V remove(K key) {
         V value = null;
 
-        if (map.containsKey(key)) {
+        if (containsKey(key)) {
             value = map.remove(key);
             mapListeners.valueRemoved(this, key, value);
         }
@@ -74,8 +74,10 @@
     }
 
     public void clear() {
-        map.clear();
-        mapListeners.mapCleared(this);
+        if (!isEmpty()) {
+            map.clear();
+            mapListeners.mapCleared(this);
+        }
     }
 
     public boolean containsKey(K key) {

Modified: incubator/pivot/trunk/core/src/pivot/collections/adapter/SetAdapter.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/adapter/SetAdapter.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/adapter/SetAdapter.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/adapter/SetAdapter.java Mon Jun  1 20:11:32 2009
@@ -45,22 +45,24 @@
     }
 
     public void add(E element) {
-        if (!set.contains(element)) {
+        if (!contains(element)) {
             set.add(element);
             setListeners.elementAdded(this, element);
         }
     }
 
     public void remove(E element) {
-        if (set.contains(element)) {
+        if (contains(element)) {
             set.remove(element);
             setListeners.elementRemoved(this, element);
         }
     }
 
     public void clear() {
-        set.clear();
-        setListeners.setCleared(this);
+        if (!isEmpty()) {
+            set.clear();
+            setListeners.setCleared(this);
+        }
     }
 
     public boolean contains(E element) {

Modified: incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedList.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedList.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedList.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedList.java Mon Jun  1 20:11:32 2009
@@ -21,7 +21,6 @@
 import pivot.collections.ListListener;
 import pivot.collections.Sequence;
 import pivot.util.ListenerList;
-import pivot.util.concurrent.SynchronizedListenerList;
 
 /**
  * Synchronized implementation of the {@link List} interface.
@@ -30,72 +29,89 @@
  */
 public class SynchronizedList<T> extends SynchronizedCollection<T>
     implements List<T> {
-    /**
-     * Synchronized list listener list implementation. Proxies events fired
-     * by inner list to listeners of synchronized list.
-     *
-     * @author gbrown
-     */
-    private class SynchronizedListListenerList
-        extends SynchronizedListenerList<ListListener<T>>
-        implements ListListener<T> {
+    private static class SynchronizedListListenerList<T>
+        extends ListListenerList<T> {
+        @Override
+        public synchronized void add(ListListener<T> listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(ListListener<T> listener) {
+            super.remove(listener);
+        }
+
+        @Override
         public synchronized void itemInserted(List<T> list, int index) {
-            for (ListListener<T> listener : this) {
-                listener.itemInserted(SynchronizedList.this, index);
-            }
+            super.itemInserted(list, index);
         }
 
+        @Override
         public synchronized void itemsRemoved(List<T> list, int index, Sequence<T> items) {
-            for (ListListener<T> listener : this) {
-                listener.itemsRemoved(SynchronizedList.this, index, items);
-            }
+            super.itemsRemoved(list, index, items);
         }
 
+        @Override
         public synchronized void itemUpdated(List<T> list, int index, T previousItem) {
-            for (ListListener<T> listener : this) {
-                listener.itemUpdated(SynchronizedList.this, index, previousItem);
-            }
+            super.itemUpdated(list, index, previousItem);
         }
 
+        @Override
         public synchronized void listCleared(List<T> list) {
-            for (ListListener<T> listener : this) {
-                listener.listCleared(SynchronizedList.this);
-            }
+            super.listCleared(list);
         }
 
+        @Override
         public synchronized void comparatorChanged(List<T> list, Comparator<T> previousComparator) {
-            for (ListListener<T> listener : this) {
-                listener.comparatorChanged(SynchronizedList.this, previousComparator);
-            }
+            super.comparatorChanged(list, previousComparator);
         }
     }
 
-    private SynchronizedListListenerList listListeners = new SynchronizedListListenerList();
+    private SynchronizedListListenerList<T> listListeners = new SynchronizedListListenerList<T>();
 
     public SynchronizedList(List<T> list) {
         super(list);
-
-        list.getListListeners().add(listListeners);
     }
 
     public synchronized int add(T item) {
-        return ((List<T>)collection).add(item);
+        int index = ((List<T>)collection).add(item);
+        listListeners.itemInserted(this, index);
+
+        return index;
     }
 
     public synchronized void insert(T item, int index) {
         ((List<T>)collection).insert(item, index);
+        listListeners.itemInserted(this, index);
     }
 
     public synchronized T update(int index, T item) {
-        return ((List<T>)collection).update(index, item);
+        T previousItem = ((List<T>)collection).update(index, item);
+        if (previousItem != item) {
+            listListeners.itemUpdated(this, index, previousItem);
+        }
+
+        return previousItem;
     }
 
-    public int remove (T item) {
-        return ((List<T>)collection).remove(item);
+    public synchronized int remove (T item) {
+        int index = indexOf(item);
+        if (index == -1) {
+            throw new IllegalArgumentException();
+        }
+
+        remove(index, 1);
+
+        return index;
     }
 
     public synchronized Sequence<T> remove(int index, int count) {
-        return ((List<T>)collection).remove(index, count);
+        Sequence<T> removed = ((List<T>)collection).remove(index, count);
+        if (count > 0) {
+            listListeners.itemsRemoved(this, index, removed);
+        }
+
+        return removed;
     }
 
     public synchronized T get(int index) {

Modified: incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedMap.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedMap.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedMap.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedMap.java Mon Jun  1 20:11:32 2009
@@ -21,7 +21,6 @@
 import pivot.collections.Map;
 import pivot.collections.MapListener;
 import pivot.util.ListenerList;
-import pivot.util.concurrent.SynchronizedListenerList;
 
 /**
  * Synchronized implementation of the {@link Map} interface.
@@ -30,52 +29,48 @@
  */
 public class SynchronizedMap<K, V> extends SynchronizedCollection<K>
     implements Map<K, V> {
-    /**
-     * Synchronized map listener list implementation. Proxies events fired
-     * by inner map to listeners of synchronized map.
-     *
-     * @author gbrown
-     */
-    private class SynchronizedMapListenerList
-        extends SynchronizedListenerList<MapListener<K, V>>
-        implements MapListener<K, V> {
+    private static class SynchronizedMapListenerList<K, V>
+        extends MapListenerList<K, V> {
+        @Override
+        public synchronized void add(MapListener<K, V> listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(MapListener<K, V> listener) {
+            super.remove(listener);
+        }
+
+        @Override
         public synchronized void valueAdded(Map<K, V> map, K key) {
-            for (MapListener<K, V> listener : this) {
-                listener.valueAdded(SynchronizedMap.this, key);
-            }
+            super.valueAdded(map, key);
         }
 
+        @Override
         public synchronized void valueRemoved(Map<K, V> map, K key, V value) {
-            for (MapListener<K, V> listener : this) {
-                listener.valueRemoved(SynchronizedMap.this, key, value);
-            }
+            super.valueRemoved(map, key, value);
         }
 
+        @Override
         public synchronized void valueUpdated(Map<K, V> map, K key, V previousValue) {
-            for (MapListener<K, V> listener : this) {
-                listener.valueUpdated(SynchronizedMap.this, key, previousValue);
-            }
+            super.valueUpdated(map, key, previousValue);
         }
 
+        @Override
         public synchronized void mapCleared(Map<K, V> map) {
-            for (MapListener<K, V> listener : this) {
-                listener.mapCleared(SynchronizedMap.this);
-            }
+            super.mapCleared(map);
         }
 
+        @Override
         public synchronized void comparatorChanged(Map<K, V> map, Comparator<K> previousComparator) {
-            for (MapListener<K, V> listener : this) {
-                listener.comparatorChanged(SynchronizedMap.this, previousComparator);
-            }
+            super.comparatorChanged(map, previousComparator);
         }
     }
 
-    private SynchronizedMapListenerList mapListeners = new SynchronizedMapListenerList();
+    private SynchronizedMapListenerList<K, V> mapListeners = new SynchronizedMapListenerList<K, V>();
 
     public SynchronizedMap(Map<K, V> map) {
         super(map);
-
-        map.getMapListeners().add(mapListeners);
     }
 
     @SuppressWarnings("unchecked")
@@ -85,12 +80,29 @@
 
     @SuppressWarnings("unchecked")
     public synchronized V put(K key, V value) {
-        return ((Map<K, V>)collection).put(key, value);
+        boolean update = containsKey(key);
+        V previousValue = ((Map<K, V>)collection).put(key, value);
+
+        if (update) {
+            mapListeners.valueUpdated(this, key, previousValue);
+        }
+        else {
+            mapListeners.valueAdded(this, key);
+        }
+
+        return previousValue;
     }
 
     @SuppressWarnings("unchecked")
     public synchronized V remove(K key) {
-        return ((Map<K, V>)collection).remove(key);
+        V value = null;
+
+        if (containsKey(key)) {
+            value = ((Map<K, V>)collection).remove(key);
+            mapListeners.valueRemoved(this, key, value);
+        }
+
+        return value;
     }
 
     @SuppressWarnings("unchecked")

Modified: incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedQueue.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedQueue.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedQueue.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedQueue.java Mon Jun  1 20:11:32 2009
@@ -17,6 +17,8 @@
 package pivot.collections.concurrent;
 
 import pivot.collections.Queue;
+import pivot.collections.QueueListener;
+import pivot.util.ListenerList;
 
 /**
  * Synchronized implementation of the {@link Queue} interface.
@@ -25,12 +27,38 @@
  */
 public class SynchronizedQueue<T> extends SynchronizedCollection<T>
     implements Queue<T> {
+    private static class SynchronizedQueueListenerList<T>
+        extends QueueListenerList<T> {
+        @Override
+        public synchronized void add(QueueListener<T> listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(QueueListener<T> listener) {
+            super.remove(listener);
+        }
+
+        @Override
+        public synchronized void itemEnqueued(Queue<T> queue, T item) {
+            super.itemEnqueued(queue, item);
+        }
+
+        @Override
+        public synchronized void itemDequeued(Queue<T> queue, T item) {
+            super.itemDequeued(queue, item);
+        }
+    }
+
+    private SynchronizedQueueListenerList<T> queueListeners = new SynchronizedQueueListenerList<T>();
+
     public SynchronizedQueue(Queue<T> queue) {
         super(queue);
     }
 
     public synchronized void enqueue(T item) {
         ((Queue<T>)collection).enqueue(item);
+        queueListeners.itemEnqueued(this, item);
 
         notify();
     }
@@ -45,13 +73,13 @@
      */
     public synchronized T dequeue() {
         T item = null;
-
         try {
             while (isEmpty()) {
                 wait();
             }
 
             item = ((Queue<T>)collection).dequeue();
+            queueListeners.itemDequeued(this, item);
         } catch(InterruptedException exception) {
         }
 
@@ -65,4 +93,8 @@
     public synchronized boolean isEmpty() {
         return ((Queue<T>)collection).isEmpty();
     }
+
+    public ListenerList<QueueListener<T>> getQueueListeners() {
+        return queueListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedSet.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedSet.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedSet.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedSet.java Mon Jun  1 20:11:32 2009
@@ -21,7 +21,6 @@
 import pivot.collections.Set;
 import pivot.collections.SetListener;
 import pivot.util.ListenerList;
-import pivot.util.concurrent.SynchronizedListenerList;
 
 /**
  * Synchronized implementation of the {@link Set} interface.
@@ -30,54 +29,57 @@
  */
 public class SynchronizedSet<E> extends SynchronizedCollection<E>
     implements Set<E> {
-    /**
-     * Synchronized set listener list implementation. Proxies events fired
-     * by inner set to listeners of synchronized set.
-     *
-     * @author gbrown
-     */
-    private class SynchronizedSetListenerList
-        extends SynchronizedListenerList<SetListener<E>>
-        implements SetListener<E> {
-        public void elementAdded(Set<E> set, E element) {
-            for (SetListener<E> listener : this) {
-                listener.elementAdded(set, element);
-            }
+    private static class SynchronizedSetListenerList<E>
+        extends SetListenerList<E> {
+        @Override
+        public synchronized void add(SetListener<E> listener) {
+            super.add(listener);
         }
 
-        public void elementRemoved(Set<E> set, E element) {
-            for (SetListener<E> listener : this) {
-                listener.elementRemoved(SynchronizedSet.this, element);
-            }
+        @Override
+        public synchronized void remove(SetListener<E> listener) {
+            super.remove(listener);
         }
 
-        public void setCleared(Set<E> set) {
-            for (SetListener<E> listener : this) {
-                listener.setCleared(SynchronizedSet.this);
-            }
+        @Override
+        public synchronized void elementAdded(Set<E> set, E element) {
+            super.elementAdded(set, element);
         }
 
-        public void comparatorChanged(Set<E> set, Comparator<E> previousComparator) {
-            for (SetListener<E> listener : this) {
-                listener.comparatorChanged(SynchronizedSet.this, previousComparator);
-            }
+        @Override
+        public synchronized void elementRemoved(Set<E> set, E element) {
+            super.elementRemoved(set, element);
+        }
+
+        @Override
+        public synchronized void setCleared(Set<E> set) {
+            super.setCleared(set);
+        }
+
+        @Override
+        public synchronized void comparatorChanged(Set<E> set, Comparator<E> previousComparator) {
+            super.comparatorChanged(set, previousComparator);
         }
     }
 
-    private SynchronizedSetListenerList setListeners = new SynchronizedSetListenerList();
+    private SynchronizedSetListenerList<E> setListeners = new SynchronizedSetListenerList<E>();
 
     public SynchronizedSet(Set<E> set) {
         super(set);
-
-        set.getSetListeners().add(setListeners);
     }
 
     public synchronized void add(E element) {
-        ((Set<E>)collection).add(element);
+        if (!contains(element)) {
+            ((Set<E>)collection).add(element);
+            setListeners.elementAdded(this, element);
+        }
     }
 
     public synchronized void remove(E element) {
-        ((Set<E>)collection).remove(element);
+        if (contains(element)) {
+            ((Set<E>)collection).remove(element);
+            setListeners.elementRemoved(this, element);
+        }
     }
 
     public synchronized boolean contains(E element) {

Modified: incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedStack.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedStack.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedStack.java (original)
+++ incubator/pivot/trunk/core/src/pivot/collections/concurrent/SynchronizedStack.java Mon Jun  1 20:11:32 2009
@@ -17,6 +17,8 @@
 package pivot.collections.concurrent;
 
 import pivot.collections.Stack;
+import pivot.collections.StackListener;
+import pivot.util.ListenerList;
 
 /**
  * Synchronized implementation of the {@link Stack} interface.
@@ -25,31 +27,49 @@
  */
 public class SynchronizedStack<T> extends SynchronizedCollection<T>
     implements Stack<T> {
+    private static class SynchronizedStackListenerList<T>
+        extends StackListenerList<T> {
+        @Override
+        public synchronized void add(StackListener<T> listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(StackListener<T> listener) {
+            super.remove(listener);
+        }
+
+        @Override
+        public synchronized void itemPushed(Stack<T> stack, T item) {
+            super.itemPushed(stack, item);
+        }
+
+        @Override
+        public synchronized void itemPopped(Stack<T> stack, T item) {
+            super.itemPopped(stack, item);
+        }
+    }
+
+    private SynchronizedStackListenerList<T> stackListeners = new SynchronizedStackListenerList<T>();
+
     public SynchronizedStack(Stack<T> stack) {
         super(stack);
     }
 
-    public void push(T item) {
+    public synchronized void push(T item) {
         ((Stack<T>)collection).push(item);
+        stackListeners.itemPushed(this, item);
     }
 
-    /**
-     * Removes an item from the top of the stack, blocking if the stack is
-     * currently empty.
-     *
-     * @return
-     * The item at the top of the stack, or null if the removing thread
-     * was interrupted.
-     */
-    public T pop() {
+    public synchronized T pop() {
         T item = null;
-
         try {
             while (isEmpty()) {
                 wait();
             }
 
             item = ((Stack<T>)collection).pop();
+            stackListeners.itemPopped(this, item);
         }
         catch(InterruptedException exception) {
         }
@@ -57,15 +77,15 @@
         return item;
     }
 
-    public T peek() {
+    public synchronized T peek() {
         return ((Stack<T>)collection).peek();
     }
 
-    public T poke(T item) {
-        return ((Stack<T>)collection).poke(item);
-    }
-
     public synchronized boolean isEmpty() {
         return ((Stack<T>)collection).isEmpty();
     }
+
+    public ListenerList<StackListener<T>> getStackListeners() {
+        return stackListeners;
+    }
 }

Modified: incubator/pivot/trunk/core/src/pivot/util/ListenerList.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/pivot/util/ListenerList.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/pivot/util/ListenerList.java (original)
+++ incubator/pivot/trunk/core/src/pivot/util/ListenerList.java Mon Jun  1 20:11:32 2009
@@ -22,8 +22,10 @@
 /**
  * Abstract base class for listener lists.
  * <p>
- * NOTE This class is not thread safe. For thread-safe management of events,
- * use {@link pivot.util.concurrent.SynchronizedListenerList}.
+ * NOTE This class is not inherently thread safe. Subclasses that require
+ * thread-safe access should synchronize method access appropriately. Callers
+ * must manually synchronize on the listener list instance to ensure thread
+ * safety during iteration.
  *
  * @author gbrown
  */

Modified: incubator/pivot/trunk/tools/src/pivot/tools/net/Request.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tools/src/pivot/tools/net/Request.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/tools/src/pivot/tools/net/Request.java (original)
+++ incubator/pivot/trunk/tools/src/pivot/tools/net/Request.java Mon Jun  1 20:11:32 2009
@@ -31,7 +31,6 @@
 import pivot.collections.HashMap;
 import pivot.io.IOTask;
 import pivot.util.ListenerList;
-import pivot.util.concurrent.SynchronizedListenerList;
 import pivot.util.concurrent.TaskExecutionException;
 
 /**
@@ -98,8 +97,18 @@
      *
      * @author tvolkert
      */
-    private static class RequestListenerList extends SynchronizedListenerList<RequestListener>
+    private static class RequestListenerList extends ListenerList<RequestListener>
         implements RequestListener {
+        @Override
+        public synchronized void add(RequestListener listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(RequestListener listener) {
+            super.remove(listener);
+        }
+
         public synchronized void connected(Request httpRequest) {
             for (RequestListener listener : this) {
                 listener.connected(httpRequest);

Modified: incubator/pivot/trunk/web/src/pivot/web/Query.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/src/pivot/web/Query.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/web/src/pivot/web/Query.java (original)
+++ incubator/pivot/trunk/web/src/pivot/web/Query.java Mon Jun  1 20:11:32 2009
@@ -32,7 +32,6 @@
 import pivot.serialization.Serializer;
 import pivot.util.ListenerList;
 import pivot.util.concurrent.Dispatcher;
-import pivot.util.concurrent.SynchronizedListenerList;
 
 /**
  * Abstract base class for web queries. A web query is an asynchronous operation
@@ -97,8 +96,18 @@
      *
      * @author tvolkert
      */
-    private static class QueryListenerList<V> extends SynchronizedListenerList<QueryListener<V>>
+    private static class QueryListenerList<V> extends ListenerList<QueryListener<V>>
         implements QueryListener<V> {
+        @Override
+        public synchronized void add(QueryListener<V> listener) {
+            super.add(listener);
+        }
+
+        @Override
+        public synchronized void remove(QueryListener<V> listener) {
+            super.remove(listener);
+        }
+
         public synchronized void connected(Query<V> query) {
             for (QueryListener<V> listener : this) {
                 listener.connected(query);

Modified: incubator/pivot/trunk/wtk/src/pivot/wtk/Window.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtk/Window.java?rev=780808&r1=780807&r2=780808&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtk/Window.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtk/Window.java Mon Jun  1 20:11:32 2009
@@ -802,7 +802,7 @@
             if (j < window.ownedWindows.getLength()) {
                 // There is another owned window to traverse; move down
                 // the tree
-                ownedWindowIndexes.poke(j + 1);
+                ownedWindowIndexes.update(ownedWindowIndexes.getLength() - 1, j + 1);
                 window = window.ownedWindows.get(j);
 
                 // If the window is not open, ignore it