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