From ecf7674c952a9d678fe8b6bbf9e91d89184d43e5 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 24 Dec 2007 21:16:14 +0000 Subject: [PATCH] threading bugfixes and improvements --- .../filebot/ui/FileBotPanelSelectionList.java | 4 ++ .../sfv/ChecksumComputationExecutor.java | 71 +++++++++++-------- .../filebot/ui/panel/sfv/ChecksumRow.java | 6 ++ .../filebot/ui/panel/sfv/SfvTableModel.java | 15 ++-- .../ui/panel/sfv/SfvTransferablePolicy.java | 66 ++++++++++------- 5 files changed, 98 insertions(+), 64 deletions(-) diff --git a/source/net/sourceforge/filebot/ui/FileBotPanelSelectionList.java b/source/net/sourceforge/filebot/ui/FileBotPanelSelectionList.java index 039ec4cb..8d5a08a6 100644 --- a/source/net/sourceforge/filebot/ui/FileBotPanelSelectionList.java +++ b/source/net/sourceforge/filebot/ui/FileBotPanelSelectionList.java @@ -16,6 +16,7 @@ import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.border.EmptyBorder; @@ -90,6 +91,9 @@ public class FileBotPanelSelectionList extends JList { public void actionPerformed(ActionEvent e) { selectEnabled = true; + + // bring window to front when on dnd + SwingUtilities.getWindowAncestor(FileBotPanelSelectionList.this).toFront(); } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationExecutor.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationExecutor.java index 2708f243..31de0e80 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationExecutor.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationExecutor.java @@ -22,10 +22,10 @@ public class ChecksumComputationExecutor { private static final int MINIMUM_POOL_SIZE = 1; - private boolean active = false; + private Boolean active = false; private long lastTaskCount = 0; - private static ChecksumComputationExecutor instance = null; + private static ChecksumComputationExecutor instance = new ChecksumComputationExecutor(); private LinkedBlockingQueue workQueue = new LinkedBlockingQueue(); @@ -48,25 +48,20 @@ public class ChecksumComputationExecutor { }; - private ChecksumComputationExecutor() { - - } - - - public static synchronized ChecksumComputationExecutor getInstance() { - if (instance == null) - instance = new ChecksumComputationExecutor(); - + public static ChecksumComputationExecutor getInstance() { return instance; } public void execute(ChecksumComputationTask task) { - setActive(true); + synchronized (workQueue) { + setActive(true); + + adjustPoolSize(); + + executor.execute(task); + } - adjustPoolSize(); - - executor.execute(task); fireActiveSessionTaskCountChange(); } @@ -78,7 +73,7 @@ public class ChecksumComputationExecutor { // for only a few files, use only one thread // for lots of files, use multiple threads // e.g 200 files ~ 1 thread, 1000 files ~ 2 threads, 40000 files ~ 4 threads - int recommendedPoolSize = (int) Math.max(Math.log10(Math.max(workQueue.size(), 1)), MINIMUM_POOL_SIZE); + int recommendedPoolSize = (int) Math.log10(Math.max(workQueue.size(), 1) + MINIMUM_POOL_SIZE); if (executor.getCorePoolSize() != recommendedPoolSize) executor.setCorePoolSize(recommendedPoolSize); @@ -107,22 +102,24 @@ public class ChecksumComputationExecutor { } - private synchronized void setActive(boolean b) { - if (this.active == b) - return; - - this.active = b; - - if (!this.active) { - // end of active computing session - lastTaskCount = executor.getTaskCount(); + private void setActive(boolean b) { + synchronized (active) { + if (this.active == b) + return; - // reset pool size - adjustPoolSize(); + this.active = b; + + if (!this.active) { + // end of active computing session + lastTaskCount = executor.getTaskCount(); + + // reset pool size + adjustPoolSize(); + } + + // invoke property change events on EDT + SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, null, active)); } - - // invoke property change events on EDT - SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, null, active)); } @@ -160,6 +157,20 @@ public class ChecksumComputationExecutor { } + public void clear() { + synchronized (workQueue) { + executor.purge(); + workQueue.clear(); + + adjustPoolSize(); + + if (executor.getActiveCount() == 0) { + setActive(false); + } + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java index 0429b448..a10d9a3a 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java @@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.io.File; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.regex.Matcher; @@ -77,6 +78,11 @@ public class ChecksumRow { } + public Collection getChecksums() { + return checksumMap.values(); + } + + public void putChecksum(File columnRoot, Checksum checksum) { checksumMap.put(columnRoot, checksum); } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTableModel.java b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTableModel.java index 99b4413c..bfd880bd 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTableModel.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTableModel.java @@ -30,11 +30,6 @@ public class SfvTableModel extends AbstractTableModel { private int checksumColumnsOffset = 2; - public SfvTableModel() { - - } - - @Override public String getColumnName(int columnIndex) { if (columnIndex == 0) @@ -152,16 +147,16 @@ public class SfvTableModel extends AbstractTableModel { public synchronized void clear() { + // stop any running computations for (ChecksumRow row : rows) { - for (File columnRoot : checksumColumnRoots) { - Checksum c = row.getChecksum(columnRoot); - - if (c != null) - c.cancelComputationTask(); + for (Checksum checksum : row.getChecksums()) { + checksum.cancelComputationTask(); } } + ChecksumComputationExecutor.getInstance().clear(); + checksumColumnRoots.clear(); rows.clear(); rowMap.clear(); diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java index 17c33881..68400c7e 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java @@ -6,14 +6,12 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; -import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.filebot.ui.FileFormat; import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy; -import net.sourceforge.filebot.ui.transferablepolicies.FileTransferablePolicy; import net.sourceforge.filebot.ui.transferablepolicies.MultiTransferablePolicy; @@ -30,7 +28,7 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy { } - private class SfvFilePolicy extends FileTransferablePolicy { + private class SfvFilePolicy extends BackgroundFileTransferablePolicy { @Override protected boolean accept(File file) { @@ -45,6 +43,28 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy { } + @Override + protected void process(List chunks) { + tableModel.addAll(chunks); + } + + + @Override + protected boolean load(List files) { + synchronized (ChecksumComputationExecutor.getInstance()) { + ChecksumComputationExecutor.getInstance().pause(); + + for (File file : files) { + load(file); + } + + ChecksumComputationExecutor.getInstance().resume(); + } + + return true; + } + + @Override protected boolean load(File sfvFile) { @@ -54,8 +74,6 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy { String line = null; Pattern pattern = Pattern.compile("(.*)\\s+(\\p{XDigit}{8})"); - ArrayList entries = new ArrayList(50); - while ((line = in.readLine()) != null) { if (line.startsWith(";")) continue; @@ -68,21 +86,17 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy { String filename = matcher.group(1); String checksumString = matcher.group(2); - entries.add(new SfvTableModel.Entry(filename, new Checksum(checksumString), sfvFile)); + publish(new SfvTableModel.Entry(filename, new Checksum(checksumString), sfvFile)); File compareColumnRoot = sfvFile.getParentFile(); File compareFile = new File(compareColumnRoot, filename); if (compareFile.exists()) { - entries.add(new SfvTableModel.Entry(filename, new Checksum(compareFile), compareColumnRoot)); + publish(new SfvTableModel.Entry(filename, new Checksum(compareFile), compareColumnRoot)); } } in.close(); - - if (!entries.isEmpty()) { - tableModel.addAll(entries); - } } catch (Exception e) { e.printStackTrace(); return false; @@ -124,22 +138,26 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy { if (files.isEmpty()) return true; - ChecksumComputationExecutor.getInstance().pause(); - - File firstFile = files.get(0); - - if ((files.size() == 1 && firstFile.isDirectory())) { - for (File f : firstFile.listFiles()) - load(f, firstFile, ""); - } else { - File columnRoot = firstFile.getParentFile(); + synchronized (ChecksumComputationExecutor.getInstance()) { + ChecksumComputationExecutor.getInstance().pause(); - for (File f : files) - load(f, columnRoot, ""); + File firstFile = files.get(0); + + if ((files.size() == 1 && firstFile.isDirectory())) { + for (File f : firstFile.listFiles()) { + load(f, firstFile, ""); + } + } else { + File columnRoot = firstFile.getParentFile(); + + for (File f : files) { + load(f, columnRoot, ""); + } + } + + ChecksumComputationExecutor.getInstance().resume(); } - ChecksumComputationExecutor.getInstance().resume(); - return true; }