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 KramerFriend
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 online Dirk FauthFriend
Messages: 1795
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 KramerFriend
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 messageGo to next message
Dirk Fauth is currently online Dirk FauthFriend
Messages: 1795
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.
Re: DataLayer: thread-safety [message #1517328 is a reply to message #1064817] Fri, 19 December 2014 12:21 Go to previous messageGo to next message
Chetana Barhate is currently offline Chetana BarhateFriend
Messages: 15
Registered: February 2014
Junior Member
Is the above problem solved??? We are also getting the same error in Nattable

java.lang.IndexOutOfBoundsException: Cannot get at 0 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.getDataValue(DataLayer.java:132)
at org.eclipse.nebula.widgets.nattable.layer.DataLayer.getDataValueByPosition(DataLayer.java:381)
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.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:331)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getDataValueByPosition(CompositeLayer.java:573)
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:159)
at org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper.paintCell(CellPainterWrapper.java:61)
at org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter.paintCell(BackgroundPainter.java:52)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:185)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:81)
at org.eclipse.nebula.widgets.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:106)
Re: DataLayer: thread-safety [message #1517398 is a reply to message #1517328] Fri, 19 December 2014 13:21 Go to previous messageGo to next message
Dirk Fauth is currently online Dirk FauthFriend
Messages: 1795
Registered: July 2012
Senior Member
In the current code base you can disable the automatic event handling in the GlazedListsEventLayer for a bulk update and enable it after the update is done to avoid the concurrency issue.
Re: DataLayer: thread-safety [message #1648641 is a reply to message #1064734] Wed, 04 March 2015 01:28 Go to previous messageGo to next message
Eric Snellman is currently offline Eric SnellmanFriend
Messages: 1
Registered: March 2015
Junior Member
Still not solved.



my update logic:
  Lock lock = baseEventList.getReadWriteLock().writeLock();
       try {
        lock.lock();
        glazedListsEventLayer.deactivate();
        baseEventList.clear();
        List<BlinkingRowDataFixture> collect = ??
        baseEventList.addAll(collect);
       } finally {
        lock.unlock();
        glazedListsEventLayer.activate();
       }
      timeStampOfLastDataChange.set(System.currentTimeMillis());


//I also have a paint Listener, Column count does not change
    natTable.addListener(SWT.Paint, new Listener() {
      @Override
      public void handleEvent(Event arg0) {
        long current = timeStampOfLastDataChange.get();
        if (current > 0) {
          for (int i = 0; i < natTable.getColumnCount(); i++) {
            InitializeAutoResizeColumnsCommand columnCommand = new InitializeAutoResizeColumnsCommand(natTable, i, natTable.getConfigRegistry(), new GCFactory(natTable));
            natTable.doCommand(columnCommand);
          }
          timeStampOfLastDataChange.compareAndSet(current, 0);
        }
      }
    });


At times I will get this, takes a while to have a collision
java.lang.IndexOutOfBoundsException: Cannot get at -1 on list of size 154
	at ca.odell.glazedlists.TransformedList.get(TransformedList.java:105)
	at org.eclipse.nebula.widgets.nattable.data.ListDataProvider.getRowObject(ListDataProvider.java:62)
	at org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsDataProvider.getRowObject(GlazedListsDataProvider.java:76)
	at org.eclipse.nebula.widgets.nattable.blink.BlinkLayer.getConfigLabelsByPosition(BlinkLayer.java:139)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getConfigLabelsByPosition(AbstractIndexLayerTransform.java:364)
	at org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.getConfigLabelsByPosition(SelectionLayer.java:473)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getConfigLabelsByPosition(CompositeLayer.java:576)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:354)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getConfigLabelsByPosition(CompositeLayer.java:576)
	at org.eclipse.nebula.widgets.nattable.layer.cell.AbstractLayerCell.getConfigLabels(AbstractLayerCell.java:52)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayer.getCellPainter(AbstractLayer.java:380)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getCellPainter(AbstractIndexLayerTransform.java:389)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getCellPainter(CompositeLayer.java:616)
	at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:379)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getCellPainter(CompositeLayer.java:616)
	at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:209)
	at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:88)
	at org.eclipse.nebula.widgets.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:116)
	at org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:109)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:993)
	at org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer$FreezableLayerPainter.paintLayer(CompositeFreezeLayer.java:229)
	at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:993)
	at org.eclipse.nebula.widgets.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:47)
	at org.eclipse.nebula.widgets.nattable.NatTable.paintNatTable(NatTable.java:453)
	at org.eclipse.nebula.widgets.nattable.NatTable.paintControl(NatTable.java:448)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
	at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
	at org.eclipse.swt.widgets.Display.sendEvent(Unknown Source)
	at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
	at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
	at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
	at org.eclipse.swt.widgets.Composite.WM_PAINT(Unknown Source)
	at org.eclipse.swt.widgets.Control.windowProc(Unknown Source)
	at org.eclipse.swt.widgets.Canvas.windowProc(Unknown Source)
	at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
	at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(Unknown Source)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
Error while painting table: Cannot get at -1 on list of size 154

This is on latest code:

org.eclipse.nebula.widgets.nattable.core_1.2.0.201502191002.jar
org.eclipse.nebula.widgets.nattable.extension.glazedlists_1.2.0.201502191002.jar
org.eclipse.nebula.widgets.nattable.extension.poi_1.2.0.201502191002.jar
<dependency>
<groupId>net.java.dev.glazedlists</groupId>
<artifactId>glazedlists_java15</artifactId>
<version>1.9.1</version>
</dependency>
Re: DataLayer: thread-safety [message #1649970 is a reply to message #1648641] Wed, 04 March 2015 15:53 Go to previous message
Dirk Fauth is currently online Dirk FauthFriend
Messages: 1795
Registered: July 2012
Senior Member
Does the issue also come up if you remove your paint listener?
Previous Topic:Set Background color to the selected portion in the tree..
Next Topic:Sort only specific rows in nattable
Goto Forum:
  


Current Time: Wed Sep 02 10:52:48 GMT 2015

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

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