1 11 package org.eclipse.jface.viewers.deferred; 12 13 14 15 24 final class ConcurrentTableUpdator { 25 28 private AbstractVirtualTable table; 29 30 35 private Object [] sentObjects = new Object [0]; 36 37 40 private IntHashMap knownIndices = new IntHashMap(); 41 42 46 private Object [] knownObjects = new Object [0]; 47 48 private static final int MIN_FLUSHLENGTH = 64; 50 51 56 private int[] pendingClears = new int[MIN_FLUSHLENGTH]; 57 58 64 private int lastClear = 0; 65 66 69 private volatile Range lastRange = new Range(0,0); 70 71 74 private volatile boolean updateScheduled; 75 76 79 private volatile boolean disposed = false; 80 81 85 public final static class Range { 86 int start = 0; 87 int length = 0; 88 89 93 public Range(int s, int l) { 94 start = s; 95 length = l; 96 } 97 } 98 99 103 Runnable uiRunnable = new Runnable () { 104 public void run() { 105 updateScheduled = false; 106 if(!table.getControl().isDisposed()) { 107 updateTable(); 108 } 109 } 110 }; 111 112 117 public ConcurrentTableUpdator(AbstractVirtualTable table) { 118 this.table = table; 119 } 120 121 124 public void dispose() { 125 disposed = true; 126 } 127 128 133 public boolean isDisposed() { 134 return disposed; 135 } 136 137 142 public Range getVisibleRange() { 143 return lastRange; 144 } 145 146 152 public void clear(Object toFlush) { 153 synchronized(this) { 154 int currentIdx = knownIndices.get(toFlush, -1); 155 156 if (currentIdx == -1) { 158 return; 159 } 160 161 pushClear(currentIdx); 162 } 163 164 } 165 166 171 public void setTotalItems(int newTotal) { 172 synchronized (this) { 173 if (newTotal != knownObjects.length) { 174 if (newTotal < knownObjects.length) { 175 for (int i = newTotal; i < knownObjects.length; i++) { 177 Object toFlush = knownObjects[i]; 178 179 if (toFlush != null) { 180 knownIndices.remove(toFlush); 181 } 182 } 183 } 184 185 int minSize = Math.min(knownObjects.length, newTotal); 186 187 Object [] newKnownObjects = new Object [newTotal]; 188 System.arraycopy(knownObjects, 0, newKnownObjects, 0, minSize); 189 knownObjects = newKnownObjects; 190 191 scheduleUIUpdate(); 192 } 193 } 194 } 195 196 201 private void pushClear(int toClear) { 202 203 if (toClear >= sentObjects.length) { 205 return; 206 } 207 208 if (sentObjects[toClear] == null) { 210 return; 211 } 212 213 sentObjects[toClear] = null; 215 216 if (lastClear >= pendingClears.length) { 217 int newCapacity = Math.min(MIN_FLUSHLENGTH, lastClear * 2); 218 int[] newPendingClears = new int[newCapacity]; 219 System.arraycopy(pendingClears, 0, newPendingClears, 0, lastClear); 220 pendingClears = newPendingClears; 221 } 222 223 pendingClears[lastClear++] = toClear; 224 } 225 226 233 public void replace(Object value, int idx) { 234 synchronized(this) { 237 Object oldObject = knownObjects[idx]; 238 239 if (oldObject != value) { 240 if (oldObject != null) { 241 knownIndices.remove(oldObject); 242 } 243 244 knownObjects[idx] = value; 245 246 if (value != null) { 247 int oldIndex = knownIndices.get(value, -1); 248 if (oldIndex != -1) { 249 knownObjects[oldIndex] = null; 250 pushClear(oldIndex); 251 } 252 253 knownIndices.put(value, idx); 254 } 255 256 pushClear(idx); 257 258 scheduleUIUpdate(); 259 } 260 } 261 } 262 263 267 private void scheduleUIUpdate() { 268 synchronized(this) { 269 if (!updateScheduled) { 270 updateScheduled = true; 271 if(!table.getControl().isDisposed()) { 272 table.getControl().getDisplay().asyncExec(uiRunnable); 273 } 274 } 275 } 276 } 277 278 279 284 public void checkVisibleRange(int includeIndex) { 285 int start = Math.min(table.getTopIndex() - 1, includeIndex); 286 int length = Math.max(table.getVisibleItemCount(), includeIndex - start); 287 Range r = lastRange; 288 289 if (start != r.start || length != r.length) { 290 updateTable(); 291 } 292 } 293 294 299 private void updateTable() { 300 301 synchronized(this) { 302 303 if (sentObjects.length != knownObjects.length) { 305 Object [] newSentObjects = new Object [knownObjects.length]; 306 System.arraycopy(newSentObjects, 0, sentObjects, 0, 307 Math.min(newSentObjects.length, sentObjects.length)); 308 sentObjects = newSentObjects; 309 table.setItemCount(newSentObjects.length); 310 } 311 312 int start = Math.min(table.getTopIndex(), knownObjects.length); 314 int length = Math.min(table.getVisibleItemCount(), knownObjects.length - start); 315 int itemCount = table.getItemCount(); 316 317 int oldStart = lastRange.start; 318 int oldLen = lastRange.length; 319 320 lastRange = new Range(start, length); 325 326 for(int idx = 0; idx < oldLen; idx++) { 328 int row = idx + oldStart; 329 330 if (row < itemCount && (row < start || row >= start + length)) { 332 333 if (sentObjects[row] == null) { 338 table.clear(row); 339 } 340 } 341 } 342 343 if (lastClear > 0) { 345 for (int i = 0; i < lastClear; i++) { 346 int row = pendingClears[i]; 347 348 if (row < sentObjects.length) { 349 table.clear(row); 350 } 351 } 352 353 if (pendingClears.length > MIN_FLUSHLENGTH) { 354 pendingClears = new int[MIN_FLUSHLENGTH]; 355 } 356 lastClear = 0; 357 } 358 359 for (int idx = 0; idx < length; idx++) { 361 int row = idx + start; 362 363 Object obj = knownObjects[row]; 364 if (obj != null && obj != sentObjects[idx]) { 365 table.replace(obj, row); 366 sentObjects[idx] = obj; 367 } 368 } 369 370 } 371 } 372 373 378 public Object [] getKnownObjects() { 379 return knownObjects; 380 } 381 382 } 383 | Popular Tags |