Home » Eclipse Projects » NatTable » Update a Table with GroupByDataLayer on a Background Thread("Best practices" for safely updating a table with grouping on a backround thread.)
Update a Table with GroupByDataLayer on a Background Thread [message #1432008] |
Fri, 26 September 2014 13:21 |
Frank Mosebach Messages: 7 Registered: September 2014 |
Junior Member |
|
|
Hi,
we're using the NatTable (v.1.1.0) in an eclipse RCP client application (platform version 4.3).
As we need to utilize the table's grouping features, we set up the table with a GroupByDataLayer as data layer. When constructing the GroupByDataLayer, we provide our own EventList implementation, because we need to propagate updates from an underlying data store that contains the actual "row objects" to the table's data model.
The workflow when the table is updated in response to changes in the underlying data store could be outlined as follows:
(1) The data store is updated (rows are added or removed) on a background thread.
(2) The EventList of the table's GroupByDataLayer receives a notification from the data store.
(3) The EventList updates its contents according to the received notification and forwards corresponding events to subscribed listeners using its ListEventAssembler. Concurrent access to the EventList from different threads is safeguarded using the "Glazed List" locking support.
(4) As the GroupByDataLayer's underlying TreeList listens to notifications emitted by the EventList, it updates itself accordingly and in turn notifies subscribed listeners.
(5) A listener that has been added to the TreeList puts a job on the SWT event queue that will fire a StructuralRefreshEvent from the GroupByDataLayer to make the table update its presentation.
The problem we're facing with this set-up is that we frequently get into situations where an exception is thrown, because the ui thread "sees" the table's data model in an inconsistent state while it is being updated on a background thread as described above.
For example, we get a NullPointerException on the ui thread with the following stack trace...
FourColorTree<T0>.indexOfNode(Element<T0>, byte) line: 818
TreeList<E>.subtreeSize(int, boolean, boolean) line: 242
TreeList<E>.subtreeSize(int, boolean) line: 249
TreeList<E>.hasChildren(int) line: 310
GlazedListTreeData<T>.hasChildren(int) line: 86
GlazedListTreeRowModel<T>(AbstractTreeRowModel<T>).hasChildren(int) line: 55
TreeLayer.getConfigLabelsByPosition(int, int) line: 137
ViewportLayer(AbstractLayerTransform).getConfigLabelsByPosition(int, int) line: 316
...
...while data model is being updated on a background thread:
FourColorTree<T0>.convertIndexColor(int, byte, byte) line: 902
TreeList$FinderInserter.findOrInsertNode(int) line: 884
TreeList$FinderInserter.access$1800(TreeList$FinderInserter, int) line: 857
TreeList<E>.listChanged(ListEvent<Node<E>>) line: 495
ListEventAssembler$ListEventFormat.fire(EventList<E>, ListEvent<E>, ListEventListener<? super E>) line: 424
ListEventAssembler$ListEventFormat.fire(Object, Object, Object) line: 421
SequenceDependenciesEventPublisher$SubjectAndListener<Subject,Listener,Event>.firePendingEvent() line: 445
SequenceDependenciesEventPublisher.fireEvent(Subject, Event, EventFormat<Subject,Listener,Event>) line: 344
ListEventAssembler<E>.commitEvent() line: 317
...
Has anybody run into similar problems when updating a table with grouping from a background thread? What are your suggested "best practices" for the described scenario?
|
|
|
Re: Update a Table with GroupByDataLayer on a Background Thread [message #1432045 is a reply to message #1432008] |
Fri, 26 September 2014 14:26 |
Dirk Fauth Messages: 2902 Registered: July 2012 |
Senior Member |
|
|
If I understand correctly your issue is that the list is updated again while the update in the NatTable instance is still processed. So you have concurrent access to the list from the UI thread and the background thread.
Quote:A listener that has been added to the TreeList puts a job on the SWT event queue that will fire a StructuralRefreshEvent from the GroupByDataLayer to make the table update its presentation.
I'm not sure if it would help, but why aren't you using the GlazedListsEventLayer? This layer is intended to do exactly what you are doing with your custom listener. The GlazedListsEventLayer for example adds a delay of 100ms to collect multiple events to fire only one refresh into NatTable instead of several that might collide.
[Updated on: Fri, 26 September 2014 14:51] Report message to a moderator
|
|
|
Re: Update a Table with GroupByDataLayer on a Background Thread [message #1434015 is a reply to message #1432045] |
Mon, 29 September 2014 14:51 |
Frank Mosebach Messages: 7 Registered: September 2014 |
Junior Member |
|
|
Hi Dirk,
Quote:
If I understand correctly your issue is that the list is updated again while the update in the NatTable instance is still processed. So you have concurrent access to the list from the UI thread and the background thread.
Yes, exactly. And in order to get that right we need to know which particular measures must be taken when configuring the table (regarding its data providers etc.) for concurrent model updates.
We're obviously having some problems with concurrency , and it's not unlikely that the cause is in our code. Hence we just want to make sure that we're on track reagarding the table set-up.
Using the GlazedListsEventLayer, as you suggested, could possibly improve rendering performance but IMO does not solve our problems regarding inconsistent model state.
For example, when looking at the sources of GlazedListsDataProvider, which is employed by GroupByDataLayer as data provider, you can see that it guards concurrent access to the underlying list for two accessors (getRowObject, getDataValue), but not for other access paths. That's not entirely thread safe IMO.
Does that mean we need to implement our own data provider to achieve thread safety, or am I just overlooking something?
Thanks,
Frank
|
|
|
Re: Update a Table with GroupByDataLayer on a Background Thread [message #1434029 is a reply to message #1434015] |
Mon, 29 September 2014 15:10 |
Dirk Fauth Messages: 2902 Registered: July 2012 |
Senior Member |
|
|
Well, to be honest, I'm not sure. But it sounds correct.
As you currently facing the issues, why don't you try to implement a custom IDataProvider that is completely thread safe, maybe based on the GlazedListsDataProvider. And if it solves your issue, contribute that solution?
I'm also not sure if GlazedListTreeData needs to be checked for concurrency issues, as the stack trace you posted initially are pointing to that.
Although, if you are using ThreadSafeList, most of the actions on the list should be thread safe.
But looking at the TreeList Javadoc,
Quote:This class is thread ready but not thread safe.
How are you buildingthe TreeList.Format path? I know that in some of our examples there is a really lazy implementation that uses Collection.reverse() which sometimes hurts.
|
|
|
Goto Forum:
Current Time: Tue Apr 23 07:02:24 GMT 2024
Powered by FUDForum. Page generated in 0.03640 seconds
|