Skip to content

Commit

Permalink
BranchGraph: Add a read-write-lock to prevent rendering during rebuild.
Browse files Browse the repository at this point in the history
Read and write accesses to the branch graph are now protected by a
read-write-lock. The LineageTreeLayoutImp acquires a read-lock during
rendering. And ModelBranchGraph write-locks itself during graphRebuilt().

This commit fixes a ConcurrentModificationException that occurred on some
datasets, when the "TrackScheme Hierarchy" window was shown for the first
time.
  • Loading branch information
maarzt authored and tinevez committed May 7, 2023
1 parent 481881d commit 2cb97e1
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public TrackSchemeGraph< BranchSpot, BranchLink > createViewGraph( final MamutAp
final GraphIdBimap< BranchSpot, BranchLink > idmap = graph.getGraphIdBimap();
final ModelGraphProperties< BranchSpot, BranchLink > properties = new MyModelGraphProperties( graph );
final TrackSchemeGraph< BranchSpot, BranchLink > trackSchemeGraph =
new TrackSchemeGraph<>( graph, idmap, properties );
new TrackSchemeGraph<>( graph, idmap, properties, graph.getLock() );
return trackSchemeGraph;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

import net.imglib2.RealLocalizable;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* A branch-graph specific for {@link ModelGraph}, whose vertices implements the
* {@link RealLocalizable} and {@link HasTimepoint} interfaces, exposing the
Expand All @@ -48,6 +50,7 @@
public class ModelBranchGraph
extends BranchGraphImp< Spot, Link, BranchSpot, BranchLink, BranchSpotPool, BranchLinkPool, ByteMappedElement >
{
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

public ModelBranchGraph( final ModelGraph graph )
{
Expand All @@ -60,6 +63,11 @@ public ModelBranchGraph( final ModelGraph graph, final int initialCapacity )
new BranchSpotPool( initialCapacity, graph.vertices().getRefPool() ) ) );
}

public ReentrantReadWriteLock getLock()
{
return lock;
}

@Override
public BranchSpot init( final BranchSpot branchVertex, final Spot branchStart, final Spot branchEnd )
{
Expand All @@ -71,4 +79,31 @@ public BranchLink init( final BranchLink branchEdge, final Link edge )
{
return branchEdge.init();
}

@Override
public void graphRebuilt()
{
if ( lock == null )
{
// NB: graphRebuilt() is called the first time, even before the lock
// is initialized. This is because the super class (BranchGraphImp)
// calls graphRebuilt() in its constructor.
// But that's not a problem. We don't need to use the lock while the
// constructor is run, since no other thread can access the
// branch graph before the constructor finished.
super.graphRebuilt();
}
else
{
lock.writeLock().lock();
try
{
super.graphRebuilt();
}
finally
{
lock.writeLock().unlock();
}
}
}
}

0 comments on commit 2cb97e1

Please sign in to comment.