I think I may have found a reproducible "test case" for the following exception:
java.util.ConcurrentModificationException: Cannot begin a new event while another event is in progress by thread, main
I have my glazed lists update/replace/delete methods wrapped in a class so that everything is always locked, and the method I use to reproduce the exceptions is this;
/**
* Replaces one entry with another in the same position of the table. Does nothing if the old object is not found in
* the table.
*
* @param oldEntry Old object to replace
* @param newEntryNew replacement object
* @param index index of message to replace, -1 to have it calculated for you (slow)
*/
public boolean replace(IDataObject oldEntry, IDataObject newEntry, int index) {
try {
_eventList.getReadWriteLock().writeLock().lock();
if (index == -1) {
index = _eventList.indexOf(oldEntry);
}
if (index != -1) {
_eventList.set(index, newEntry);
return true;
}
}
catch (Exception err) {
LogManager.error(err);
}
finally {
_eventList.getReadWriteLock().writeLock().unlock();
}
return false;
}
As you can see from the method signature, it either takes an index or tries to find it. In my test code I continuously (once per second) replace 20 items in a table with 20 new items, from position 20 to 1 (or 19 to 0 if you will) (we show newest entries at the top in the table).
As our tables can be really large, we keep a Primary Key index that's updated every time the list is modified so that they match, thus we can find the index faster than the table can via object comparison.
In any case, one tester reported the exception and I couldn't for the life of me reproduce it until I got his full log and saw that the originating exception was a replace call with an index that was larger than the event list itself;
java.lang.IndexOutOfBoundsException: Index: 35, Size: 26
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at ca.odell.glazedlists.BasicEventList.set(BasicEventList.java:188)
And following that exception, tons of the ConcurrentModificationExceptions.
So what I did was that in our loop that calls replace() I halted the code in debug mode and forced an index to be 21 (table has 20 entries, so 21 is out of bounds) and then I traced it to see what happened.
First IndexOutOfBounds is thrown when it tries to do _eventList.set(index, newEntry); That's expected. Then it reaches _eventList.getReadWriteLock().writeLock().unlock(); and returns false. All expected.
However, on the next iteration to replace, even if the update index is valid (code paused, forced 21 index removed), the ConcurrentModificationException is thrown every time for every method call.
So I guess my question is twofold;
1. Is there something I'm doing obviously wrong in the above code?
2. Is something not reset with the event list when it gets an IndexOutOfBounds exception that's the cause of this? It seems to me if the list is unlocked again there shouldn't be a double modification on the next iteration.
It's worth adding that all of this is SWT RCP code with a Nat table behind it, so table updates are originating from a UI thread.
Regards,
Emil