1 package org.mortbay.util;
2
3 import java.util.Iterator;
4 import java.util.NoSuchElementException;
5
6 import org.mortbay.util.ArrayQueue;
7
8 public class ArrayIdQueue<E> extends ArrayQueue<E>
9 {
10 private long[] _ids;
11 private long _currentId;
12 private int _unacked;
13 private int _cursor;
14
15
16 public ArrayIdQueue()
17 {
18 super();
19 _ids=new long[DEFAULT_CAPACITY];
20 }
21
22
23 public ArrayIdQueue(int capacity)
24 {
25 super(capacity);
26 _ids=new long[capacity];
27 }
28
29
30 public ArrayIdQueue(int initCapacity, int growBy)
31 {
32 super(initCapacity,growBy);
33 _ids=new long[initCapacity];
34 }
35
36
37 public ArrayIdQueue(int initCapacity, int growBy, Object lock)
38 {
39 super(initCapacity,growBy,lock);
40 _ids=new long[initCapacity];
41 }
42
43
44
45
46
47
48 public int getUnackedIndex()
49 {
50 return _unacked;
51 }
52
53
54 public void incrementUnackedIndex()
55 {
56 _unacked++;
57 }
58
59
60 public void decrementUnackedIndex()
61 {
62 _unacked--;
63 }
64
65
66
67
68
69 public long getCurrentId()
70 {
71 return _currentId;
72 }
73
74 public void setCurrentId(int currentId)
75 {
76 _currentId=currentId;
77 }
78
79 public void incrementCurrentId()
80 {
81 _currentId++;
82 }
83
84
85 public boolean add(E e)
86 {
87 synchronized (_lock)
88 {
89 int nextSlot=_nextSlot;
90 super.add(e);
91 _ids[nextSlot]=_currentId;
92 }
93 return true;
94 }
95
96
97 public void addUnsafe(E e)
98 {
99 int nextSlot=_nextSlot;
100 super.addUnsafe(e);
101 _ids[nextSlot]=_currentId;
102
103 }
104
105
106 public boolean offer(E e)
107 {
108 int nextSlot = _nextSlot;
109 int nextE = _nextE;
110
111 _ids[nextSlot]=_currentId;
112
113 boolean offer = super.offer(e);
114 if(!offer) return false;
115
116 long[] ids=new long[_elements.length];
117
118 int split=_ids.length-nextE;
119 if (split>0)
120 System.arraycopy(_ids,nextE,ids,0,split);
121 if (nextE!=0)
122 System.arraycopy(_ids,0,ids,split,nextSlot);
123
124 _ids=ids;
125
126 return offer;
127
128 }
129
130
131 public long getAssociatedId(int index)
132 {
133 synchronized(_lock)
134 {
135 if (index<0 || index>=_size)
136 throw new IndexOutOfBoundsException("!("+0+"<"+index+"<="+_size+")");
137 int i = _nextE+index;
138 if (i>=_ids.length)
139 i-=_ids.length;
140 return _ids[i];
141 }
142 }
143
144
145 public long getAssociatedIdUnsafe(int index)
146 {
147 int i = _nextE+index;
148 if (i>=_ids.length)
149 i-=_ids.length;
150 return _ids[i];
151 }
152
153
154 public E remove(int index)
155 {
156 synchronized(_lock)
157 {
158 int nextSlot = _nextSlot;
159 E e = super.remove(index);
160
161 int i = _nextE+index;
162 if (i>=_ids.length)
163 i-=_ids.length;
164
165 if (i<nextSlot)
166 {
167 System.arraycopy(_ids,i+1,_ids,i,nextSlot-i);
168 nextSlot--;
169 }
170 else
171 {
172 System.arraycopy(_ids,i+1,_ids,i,_ids.length-1);
173 if (nextSlot>0)
174 {
175 _ids[_ids.length]=_ids[0];
176 System.arraycopy(_ids,1,_ids,0,nextSlot-1);
177 nextSlot--;
178 }
179 else
180 nextSlot=_ids.length-1;
181
182 }
183
184 return e;
185 }
186 }
187
188
189 public E set(int index, E element)
190 {
191 synchronized(_lock)
192 {
193 E old = super.set(index, element);
194
195 int i = _nextE+index;
196 if (i>=_ids.length)
197 i-=_ids.length;
198
199 _ids[i]=_currentId;
200 return old;
201 }
202 }
203
204
205 public void add(int index, E element)
206 {
207 synchronized(_lock)
208 {
209 int nextSlot = _nextSlot;
210 super.add(index, element);
211
212 if (index==_size)
213 {
214 _ids[index] = _currentId;
215 }
216 else
217 {
218 int i = _nextE+index;
219 if (i>=_ids.length)
220 i-=_ids.length;
221
222 if (i<nextSlot)
223 {
224 System.arraycopy(_ids,i,_ids,i+1,nextSlot-i);
225 _ids[i]=_currentId;
226 }
227 else
228 {
229 if (nextSlot>0)
230 {
231 System.arraycopy(_ids,0,_ids,1,nextSlot);
232 _ids[0]=_ids[_ids.length-1];
233 }
234
235 System.arraycopy(_ids,i,_ids,i+1,_ids.length-i-1);
236 _ids[i]=_currentId;
237 }
238 }
239 }
240 }
241
242 public E get(int index)
243 {
244 _cursor = index;
245 return super.get(index);
246 }
247
248 protected void grow()
249 {
250 int nextE=_nextE;
251 int nextSlot=_nextSlot;
252
253 super.grow();
254
255 long[] Ids=new long[_elements.length];
256 int split=_ids.length - nextE;
257 if (split > 0)
258 System.arraycopy(_ids,nextE,Ids,0,split);
259 if (nextE != 0)
260 System.arraycopy(_ids,0,Ids,split,nextSlot);
261
262 _ids=Ids;
263 }
264
265
266
267
268
269 public ArrayIdIterator idIterator()
270 {
271 return new ArrayIdIterator(iterator());
272 }
273
274 public class ArrayIdIterator implements Iterator<E>
275 {
276 private Iterator<E> _iterator;
277
278 public ArrayIdIterator(Iterator<E> iterator)
279 {
280 _iterator = iterator;
281 }
282
283
284
285
286
287 public long associatedId()
288 {
289 try {
290 long nextId = ArrayIdQueue.this.getAssociatedId(ArrayIdQueue.this._cursor);
291 return nextId;
292 } catch(IndexOutOfBoundsException e) {
293 throw new NoSuchElementException();
294 }
295 }
296
297
298 public long nextId() {
299 try {
300 next();
301 long nextId = ArrayIdQueue.this.getAssociatedId(ArrayIdQueue.this._cursor);
302 return nextId;
303 } catch(IndexOutOfBoundsException e) {
304 throw new NoSuchElementException();
305 }
306 }
307
308
309 public boolean hasNext()
310 {
311 return _iterator.hasNext();
312 }
313
314
315 public E next()
316 {
317 return _iterator.next();
318 }
319
320
321 public void remove()
322 {
323 _iterator.remove();
324 }
325 }
326
327 }