]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.thread/src/org/simantics/utils/threads/internal/ListenerList.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils.thread / src / org / simantics / utils / threads / internal / ListenerList.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 /*
13  * 12.6.2007
14  */
15 package org.simantics.utils.threads.internal;
16
17 import java.lang.reflect.Array;
18
19 /**
20  * ListenerList is an efficient and synchronized list of listeners.
21  * The class is optimized for quick getListeners and slow add/remove.
22  * 
23  * @author Toni Kalajainen
24  */
25 public class ListenerList<T> {
26     
27     /**
28      * Array of listeners
29      */
30     private volatile T [] array;
31     
32     /** 
33      * The class of T
34      */
35     private final Class<T> componentType;
36            
37     /**
38      * Construct new Listener List
39      * @param componentType the class of the listener type
40      */
41     public ListenerList(Class<T> componentType)
42     {
43         this.componentType = componentType;
44         array = createArray(0);
45     }
46     
47     public T[] getListeners()
48     {
49         return array;
50     }
51     
52     public synchronized void add(T listener)
53     {
54         int oldLength = array.length;
55         int newLength = oldLength + 1;
56         T newArray[] = createArray(newLength);
57         System.arraycopy(array, 0, newArray, 0, oldLength);
58         newArray[oldLength] = listener;
59         array = newArray;
60     }
61     
62     /**
63      * Removes the first occurance of listener.
64      * If the listener is added multiple times, then it must be removed
65      * as many times.
66      * 
67      * @param listener a listener
68      * @return the listener that was removed from the list
69      */
70     public synchronized boolean remove(T listener)
71     {
72         int pos = getPos(listener);
73         if (pos<0) return false;
74         
75         int oldLength = array.length;
76         int newLength = oldLength -1;
77         T newArray[] = createArray(newLength);
78         
79         // Copy beginning
80         if (pos>0)
81             System.arraycopy(array, 0, newArray, 0, pos);
82         
83         // Copy ending
84         if (pos<newLength)
85             System.arraycopy(array, pos+1, newArray, pos, newLength-pos);
86         
87         array = newArray;
88         return true;
89     }        
90     
91     private synchronized int getPos(T listener)
92     {
93         for (int i=0; i<array.length; i++)
94             if (array[i] == listener)
95                 return i;
96         return -1;
97     }
98     
99     public int size()
100     {
101         return array.length;
102     }
103     
104     public boolean isEmpty()
105     {
106         return array.length == 0;
107     }
108     
109     public void clear()
110     {
111         array = createArray(0);
112     }
113     
114     @SuppressWarnings("unchecked")
115     private T[] createArray(int size)
116     {
117         return (T[]) Array.newInstance(componentType, size);
118     }
119     
120 }