From 3c4f362ad20d1254d67fd60da2185392afe3c155 Mon Sep 17 00:00:00 2001 From: Rohit Yengisetty Date: Tue, 10 Feb 2015 10:44:26 -0800 Subject: [PATCH] CM File Manager - Make AsyncResultExecutable's cancel() and end() innocuous Ensure that cancel() and end() calls don't block the current thread unnecessarily waiting for a notify(). Change-Id: I05843c8e1bdf880243e1fe9a226809aeaf33986b --- .../filemanager/activities/SearchActivity.java | 9 +++---- .../filemanager/commands/java/FindCommand.java | 28 +++++++++++++++++----- .../filemanager/commands/secure/FindCommand.java | 20 ++++++++++++---- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/com/cyanogenmod/filemanager/activities/SearchActivity.java b/src/com/cyanogenmod/filemanager/activities/SearchActivity.java index 7c6bb2f..b632c78 100644 --- a/src/com/cyanogenmod/filemanager/activities/SearchActivity.java +++ b/src/com/cyanogenmod/filemanager/activities/SearchActivity.java @@ -241,6 +241,7 @@ public class SearchActivity extends Activity @Override public void run() { try { + mExecutable = null; mAdapter.stopStreaming(); int resultsSize = mAdapter.resultsSize(); mStreamingSearchProgress.setVisibility(View.INVISIBLE); @@ -481,7 +482,7 @@ public class SearchActivity extends Activity super.onPause(); // stop search if the activity moves out of the foreground if (mExecutable != null) { - mExecutable.cancel(); + mExecutable.end(); } } @@ -973,7 +974,7 @@ public class SearchActivity extends Activity case KeyEvent.KEYCODE_BACK: // release Console lock held by the async search task if (mExecutable != null) { - mExecutable.cancel(); + mExecutable.end(); } back(true, null, false); return true; @@ -991,7 +992,7 @@ public class SearchActivity extends Activity case android.R.id.home: // release Console lock held by the async search task if (mExecutable != null) { - mExecutable.cancel(); + mExecutable.end(); } back(true, null, false); return true; @@ -1008,7 +1009,7 @@ public class SearchActivity extends Activity // cancel search query if in progress // *need* to do this as the async query holds a lock on the Console and we need the Console // to gather additional file info in order to process the click event - if (mSearchInProgress) mExecutable.cancel(); + if (mSearchInProgress) mExecutable.end(); try { SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position); diff --git a/src/com/cyanogenmod/filemanager/commands/java/FindCommand.java b/src/com/cyanogenmod/filemanager/commands/java/FindCommand.java index 2a7ccf5..e4f1b08 100644 --- a/src/com/cyanogenmod/filemanager/commands/java/FindCommand.java +++ b/src/com/cyanogenmod/filemanager/commands/java/FindCommand.java @@ -43,8 +43,8 @@ public class FindCommand extends Program implements FindExecutable { private final String[] mQueryRegExp; private final ConcurrentAsyncResultListener mAsyncResultListener; - private boolean mCancelled; - private boolean mEnded; + private volatile boolean mCancelled; + private volatile boolean mEnded; private final Object mSync = new Object(); /** @@ -110,6 +110,15 @@ public class FindCommand extends Program implements FindExecutable { findRecursive(f); } + // record program's execution termination + synchronized (mSync) { + mEnded = true; + // account for the delay between the end of findRecursive and setting program + // termination flag (mEnded) + // notify again in case a thread entered wait state since + mSync.notify(); + } + if (this.mAsyncResultListener != null) { this.mAsyncResultListener.onAsyncEnd(this.mCancelled); } @@ -187,8 +196,12 @@ public class FindCommand extends Program implements FindExecutable { public boolean cancel() { try { synchronized (this.mSync) { - this.mCancelled = true; - this.mSync.wait(5000L); + // ensure the program is running before attempting to cancel + // there won't be a corresponding lock.notify() otherwise + if (!mEnded) { + this.mCancelled = true; + this.mSync.wait(5000L); + } } } catch (Exception e) {/**NON BLOCK**/} return true; @@ -201,8 +214,11 @@ public class FindCommand extends Program implements FindExecutable { public boolean end() { try { synchronized (this.mSync) { - this.mEnded = true; - this.mSync.wait(5000L); + // ensure the program is running before attempting to terminate + if (!mEnded) { + this.mEnded = true; + this.mSync.wait(5000L); + } } } catch (Exception e) {/**NON BLOCK**/} return true; diff --git a/src/com/cyanogenmod/filemanager/commands/secure/FindCommand.java b/src/com/cyanogenmod/filemanager/commands/secure/FindCommand.java index 33d0ace..35289e5 100644 --- a/src/com/cyanogenmod/filemanager/commands/secure/FindCommand.java +++ b/src/com/cyanogenmod/filemanager/commands/secure/FindCommand.java @@ -44,8 +44,8 @@ public class FindCommand extends Program implements FindExecutable { private final String[] mQueryRegExp; private final ConcurrentAsyncResultListener mAsyncResultListener; - private boolean mCancelled; - private boolean mEnded; + private volatile boolean mCancelled; + private volatile boolean mEnded; private final Object mSync = new Object(); /** @@ -118,6 +118,15 @@ public class FindCommand extends Program implements FindExecutable { // Find the data findRecursive(f); + // record program's execution termination + synchronized (mSync) { + mEnded = true; + // account for the delay between the end of findRecursive and setting program + // termination flag (mEnded) + // notify again in case a thread entered wait state since + mSync.notify(); + } + if (this.mAsyncResultListener != null) { this.mAsyncResultListener.onAsyncEnd(this.mCancelled); } @@ -198,7 +207,9 @@ public class FindCommand extends Program implements FindExecutable { @Override public boolean cancel() { try { - synchronized (this.mSync) { + // ensure the program is running before attempting to cancel + // there won't be a corresponding lock.notify() otherwise + if (!mEnded) { this.mCancelled = true; this.mSync.wait(5000L); } @@ -212,7 +223,8 @@ public class FindCommand extends Program implements FindExecutable { @Override public boolean end() { try { - synchronized (this.mSync) { + // ensure the program is running before attempting to terminate + if (!mEnded) { this.mEnded = true; this.mSync.wait(5000L); } -- 2.11.0