Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.common')
-rw-r--r--bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/ListenerList.java80
1 files changed, 70 insertions, 10 deletions
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/ListenerList.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/ListenerList.java
index a746b742c..c62d79181 100644
--- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/ListenerList.java
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/ListenerList.java
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.core.runtime;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
/**
* This class is a thread safe list that is designed for storing lists of listeners.
* The implementation is optimized for minimal memory footprint, frequent reads
@@ -18,7 +21,7 @@ package org.eclipse.core.runtime;
* to the underlying array data structure for reading, with the trust that they will
* not modify the underlying array.
* <p>
- * <a name="same">A listener list handles the <i>same</i> listener being added
+ * <a name="same"></a>A listener list handles the <i>same</i> listener being added
* multiple times, and tolerates removal of listeners that are the same as other
* listeners in the list. For this purpose, listeners can be compared with each other
* using either equality or identity, as specified in the list constructor.
@@ -27,20 +30,27 @@ package org.eclipse.core.runtime;
* Use the <code>getListeners</code> method when notifying listeners. The recommended
* code sequence for notifying all registered listeners of say,
* <code>FooListener.eventHappened</code>, is:
- *
+ * </p>
* <pre>
- * Object[] listeners = myListenerList.getListeners();
- * for (int i = 0; i &lt; listeners.length; ++i) {
- * ((FooListener) listeners[i]).eventHappened(event);
+ * ListenerList&lt;FooListener&gt; fooListeners = new ListenerList<>();
+ * //...
+ * for (FooListener listener : fooListeners) {
+ * listener.eventHappened(event);
* }
* </pre>
- *
- * </p><p>
+ * <p>
+ * Alternatively, you can call {@link #getListeners()} and then use a for-loop
+ * to iterate the {@code Object[]}. This might be insignificantly faster, but
+ * it lacks type-safety and risks inadvertent modifications to the array.
+ * </p>
+ * <p>
* This class can be used without OSGi running.
* </p>
+ *
+ * @param <E> the type of listeners in this list
* @since org.eclipse.equinox.common 3.2
*/
-public class ListenerList {
+public class ListenerList<E> implements Iterable<E> {
/**
* The empty array singleton instance.
@@ -96,7 +106,7 @@ public class ListenerList {
*
* @param listener the non-<code>null</code> listener to add
*/
- public synchronized void add(Object listener) {
+ public synchronized void add(E listener) {
// This method is synchronized to protect against multiple threads adding
// or removing listeners concurrently. This does not block concurrent readers.
if (listener == null)
@@ -124,7 +134,13 @@ public class ListenerList {
* to the listener list during the notification will have no effect on
* the notification itself.
* <p>
- * Note: Callers of this method <b>must not</b> modify the returned array.
+ * Note: Callers of this method <b>must not</b> modify the returned array.
+ * </p>
+ * <p>
+ * Note: The recommended and type-safe way to iterate this list is to use
+ * an enhanced 'for' statement, see {@link ListenerList}.
+ * This method is deprecated for new code.
+ * </p>
*
* @return the list of registered listeners
*/
@@ -133,6 +149,50 @@ public class ListenerList {
}
/**
+ * Returns an iterator over all the registered listeners.
+ * The resulting iterator is unaffected by subsequent adds or removes.
+ * Use this method when notifying listeners, so that any modifications
+ * to the listener list during the notification will have no effect on
+ * the notification itself.
+ *
+ * @return an iterator
+ * @since org.eclipse.equinox.common 3.8
+ */
+ @Override
+ public Iterator<E> iterator() {
+ return new ListenerListIterator<>(listeners);
+ }
+
+ private static class ListenerListIterator<E> implements Iterator<E> {
+ private Object[] listeners;
+ private int i;
+
+ public ListenerListIterator(Object[] listeners) {
+ this.listeners = listeners;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return i < listeners.length;
+ }
+
+ @Override
+ public E next() {
+ if (i >= listeners.length) {
+ throw new NoSuchElementException();
+ }
+ @SuppressWarnings("unchecked") // (E) is safe, because #add(E) only accepts Es
+ E next = (E) listeners[i++];
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
* Returns whether this listener list is empty.
*
* @return <code>true</code> if there are no registered listeners, and

Back to the top