Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » NatTable » DataLayer: thread-safety
DataLayer: thread-safety [message #1064734] Thu, 20 June 2013 17:33 Go to next message
Steve Kramer is currently offline Steve Kramer
Messages: 8
Registered: January 2013
Junior Member
Hi

What is the preferred way to asynchronously update the data-provider of a NatTable using glazed lists ? Do all the updates to the data-provider have to be performed by the UI thread or can it be updated asynchronously by a separate worker thread and leverage the glazed lists event mechanism to trigger a thread-safe repaint of the table?

I'm currently using a BasicEventList (wrapped using GlazedLists.threadSafeList) as data-provider of the NatTable. A worker thread updates the list which automatically triggers a repaint of the table by the UI thread. Things work fine if the worker thread updates (inserts/removes) elements at low frequency but as the worker thread increases the updates I'm starting to see IndexOutOfBoundsExceptions in the UI thread (see stack trace below).

A closer look at the DataLayer.getDataValueByPosition() method shows that the calculation of the index and the access to the element using that index is implemented with two separate calls to the data-provider. Even if the data-provider itself is thread-safe it looks like the calculated index may be invalid if the worker thread removes the appropriate element in between these two calls. Some additional locking of the data-provider seems to be required to avoid this inconsistency.

I'm using the NatTable 1.0.0 release with GlazedLists 1.9 from Orbit.

Thanks
Steve




java.lang.IndexOutOfBoundsException: Cannot get at 6 on list of size 0
at ca.odell.glazedlists.TransformedList.get(TransformedList.java:105)
at ca.odell.glazedlists.TransformedList.get(TransformedList.java:106)
at org.eclipse.nebula.widgets.nattable.data.ListDataProvider.getDataValue(ListDataProvider.java:45)
at org.eclipse.nebula.widgets.nattable.layer.DataLayer.getDataValueByPosition(DataLayer.java:311)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getDataValueByPosition(AbstractIndexLayerTransform.java:333)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getDataValueByPosition(CompositeLayer.java:548)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getDataValueByPosition(CompositeLayer.java:548)
at org.eclipse.nebula.widgets.nattable.layer.cell.AbstractLayerCell.getDataValue(AbstractLayerCell.java:58)
at org.eclipse.nebula.widgets.nattable.layer.cell.CellDisplayConversionUtils.convertDataType(CellDisplayConversionUtils.java:20)
at org.eclipse.nebula.widgets.nattable.painter.cell.AbstractTextPainter.convertDataType(AbstractTextPainter.java:141)
at org.eclipse.nebula.widgets.nattable.painter.cell.TextPainter.paintCell(TextPainter.java:132)
at org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper.paintCell(CellPainterWrapper.java:61)
at org.eclipse.nebula.widgets.nattable.painter.cell.decorator.PaddingDecorator.paintCell(PaddingDecorator.java:71)
at org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper.paintCell(CellPainterWrapper.java:61)
at org.eclipse.nebula.widgets.nattable.painter.cell.decorator.LineBorderDecorator.paintCell(LineBorderDecorator.java:74)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:114)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter.paintCell(SelectionLayerPainter.java:152)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:49)
at org.eclipse.nebula.widgets.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:42)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:43)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:862)
at org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer$FreezableLayerPainter.paintLayer(CompositeFreezeLayer.java:177)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:862)
at org.eclipse.nebula.widgets.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:36)
at org.eclipse.nebula.widgets.nattable.NatTable.paintNatTable(NatTable.java:341)
at org.eclipse.nebula.widgets.nattable.NatTable.paintControl(NatTable.java:337)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:230)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4136)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1458)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1481)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1466)
at org.eclipse.swt.widgets.Control.drawWidget(Control.java:1244)
at org.eclipse.swt.widgets.Canvas.drawWidget(Canvas.java:167)
at org.eclipse.swt.widgets.Widget.drawRect(Widget.java:741)
at org.eclipse.swt.widgets.Canvas.drawRect(Canvas.java:162)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:5473)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
at org.eclipse.swt.widgets.Display.applicationNextEventMatchingMask(Display.java:4875)
at org.eclipse.swt.widgets.Display.applicationProc(Display.java:5241)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
at org.eclipse.swt.internal.cocoa.NSApplication.nextEventMatchingMask(NSApplication.java:94)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3615)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1053)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:942)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:150)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
Error while painting table: Cannot get at 6 on list of size 0
Re: DataLayer: thread-safety [message #1064744 is a reply to message #1064734] Thu, 20 June 2013 18:41 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk Fauth
Messages: 1339
Registered: July 2012
Senior Member
Do you use the GlazedListsEventLayer in your layer stack?
Re: DataLayer: thread-safety [message #1064807 is a reply to message #1064744] Fri, 21 June 2013 08:02 Go to previous messageGo to next message
Steve Kramer is currently offline Steve Kramer
Messages: 8
Registered: January 2013
Junior Member
Yes I do - my stack also contains a BlinkLayer that seems to work as expected. Updating the property of a list element correctly triggers a blink event which is visualized in the table. The layers are built up similar to the the BodyLayerStack in the builder package. The eventList used for the ListDataProvider is wrapped into a thread-safe list using GlazedLists.threadSafeList before handed over to the ListDataProvider.

The issue primarily seems to come up when elements are removed from the table by the worker thread.

bodyDataProvider = new ListDataProvider<T>(eventList, tableModel.getColumnPropertyAccessor());
bodyDataLayer = new DataLayer(bodyDataProvider);

glazedListsEventLayer = new GlazedListsEventLayer<T>(bodyDataLayer, eventList);
blinkLayer = new BlinkLayer<T>(glazedListsEventLayer, bodyDataProvider, rowIdAccessor, tableModel.getColumnPropertyAccessor(), configRegistry);

columnReorderLayer = new ColumnReorderLayer(blinkLayer);
columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);

Thanks
Re: DataLayer: thread-safety [message #1064817 is a reply to message #1064807] Fri, 21 June 2013 08:33 Go to previous message
Dirk Fauth is currently offline Dirk Fauth
Messages: 1339
Registered: July 2012
Senior Member
Hm, well it seems to be a race condition as the refresh might get triggered before the GlazedLists instance is in the correct state. But I'm not quite sure how to solve this easily.

It would cost some time to debug in detail. Also it would be great to have an example code for debugging. Still not sure how and when a fix could be made by us.
Previous Topic:RowSelection right after creation (does not work)
Next Topic:NatTable bold border between rows?
Goto Forum:
  


Current Time: Sun Oct 26 04:42:35 GMT 2014

Powered by FUDForum. Page generated in 0.02335 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software