X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FHiddenColumnsCursor.java;fp=src%2Fjalview%2Fdatamodel%2FHiddenColumnsCursor.java;h=32845049913e4406fcffe8e1c3111360b6bde8d1;hb=f149fa7699eddc4968dc5a9fa35694abcc28b0cd;hp=9d1351e963ef52f0787d1a8b093b6391ba782bc2;hpb=f7a7a1b85e3ab978220c8ccc924f3356c2a0e523;p=jalview.git diff --git a/src/jalview/datamodel/HiddenColumnsCursor.java b/src/jalview/datamodel/HiddenColumnsCursor.java index 9d1351e..3284504 100644 --- a/src/jalview/datamodel/HiddenColumnsCursor.java +++ b/src/jalview/datamodel/HiddenColumnsCursor.java @@ -21,47 +21,53 @@ package jalview.datamodel; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; public class HiddenColumnsCursor { // absolute position of first hidden column private int firstColumn; - // index of last visited region - private int regionIndex; - - // number of hidden columns before last visited region - private int hiddenSoFar; - private List hiddenColumns; + // AtomicReference to hold the current region index and hidden column count + // Could be done with synchronisation but benchmarking shows this way is 2x + // faster + private final AtomicReference cursorPos = new AtomicReference<>( + new HiddenCursorPosition(0, 0, 0)); + protected HiddenColumnsCursor() { } /** - * Set the cursor to a position + * Reset the cursor with a new hidden columns collection. Calls to resetCursor + * should be made from within a writeLock in the HiddenColumns class - since + * changes to the hiddenColumns collection require a writeLock the lock should + * already exist. * * @param hiddenCols */ protected void resetCursor(List hiddenCols) { - synchronized (this) + hiddenColumns = hiddenCols; + if ((hiddenCols != null) && (!hiddenCols.isEmpty())) { - hiddenColumns = hiddenCols; - if ((hiddenCols != null) && (!hiddenCols.isEmpty())) - { - firstColumn = hiddenColumns.get(0)[0]; - regionIndex = 0; - hiddenSoFar = 0; - } + firstColumn = hiddenColumns.get(0)[0]; + HiddenCursorPosition oldpos = cursorPos.get(); + HiddenCursorPosition newpos = new HiddenCursorPosition(0, 0, 0); + cursorPos.compareAndSet(oldpos, newpos); } } /** * Delete the region the cursor is currently at. Avoids having to reset the * cursor just because we deleted a region. + * + * Calls to updateForDeletedRegion should be made from within a writeLock in + * the HiddenColumns class - since changes to the hiddenColumns collection + * require a writeLock the lock should already exist. * * @param hiddenCols */ @@ -74,36 +80,23 @@ public class HiddenColumnsCursor // nothing changes; otherwise // we deleted the last region (index=hiddenCols.size()-1) // or the index was at the end of the alignment (index=hiddenCols.size()) - if (regionIndex >= hiddenColumns.size() - 1) + HiddenCursorPosition oldpos = cursorPos.get(); + + int index = oldpos.getRegionIndex(); + if (index >= hiddenColumns.size() - 1) { // deleted last region, index is now end of alignment - regionIndex = hiddenCols.size(); + index = hiddenCols.size(); } - } - - hiddenColumns = hiddenCols; - } - protected void updateCursor(int index, int hiddenCount) - { - synchronized (this) - { - regionIndex = index; - hiddenSoFar = hiddenCount; + // update the cursor position + HiddenCursorPosition newpos = new HiddenCursorPosition(index, + oldpos.getHiddenSoFar(), oldpos.getNumColumns()); + cursorPos.compareAndSet(oldpos, newpos); } + hiddenColumns = hiddenCols; } - protected synchronized int getIndex() - { - return regionIndex; - } - - protected synchronized int getHiddenSoFar() - { - return hiddenSoFar; - } - - /** * Get the index of the region that column is within (if column is hidden) or * which is to the right of column (if column is visible). If no hidden @@ -114,15 +107,16 @@ public class HiddenColumnsCursor * absolute position of a column in the alignment * @return region index */ - protected int findRegionForColumn(int column) + protected HiddenCursorPosition findRegionForColumn(int column) { if (hiddenColumns == null) { - return -1; + return null; } - int index = regionIndex; - int hiddenCount = hiddenSoFar; + HiddenCursorPosition oldpos = cursorPos.get(); + int index = oldpos.getRegionIndex(); + int hiddenCount = oldpos.getHiddenSoFar(); if (index == hiddenColumns.size()) { @@ -175,8 +169,10 @@ public class HiddenColumnsCursor } } } - updateCursor(index, hiddenCount); - return index; + HiddenCursorPosition newpos = new HiddenCursorPosition(index, + hiddenCount, oldpos.getNumColumns()); + cursorPos.compareAndSet(oldpos, newpos); + return newpos; } /** @@ -187,15 +183,16 @@ public class HiddenColumnsCursor * index of column in visible alignment * @return */ - protected int getHiddenOffset(int column) + protected HiddenCursorPosition getHiddenOffset(int column) { if (hiddenColumns == null) { - return -1; + return null; } - int index = getIndex(); - int hiddenCount = getHiddenSoFar(); + HiddenCursorPosition oldpos = cursorPos.get(); + int index = oldpos.getRegionIndex(); + int hiddenCount = oldpos.getHiddenSoFar(); if (column < firstColumn) { @@ -226,7 +223,10 @@ public class HiddenColumnsCursor } } - updateCursor(index, hiddenCount); - return hiddenCount; + + HiddenCursorPosition newpos = new HiddenCursorPosition(index, + hiddenCount, oldpos.getNumColumns()); + cursorPos.compareAndSet(oldpos, newpos); + return newpos; } }