aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod
diff options
context:
space:
mode:
authorJean Chalard <jchalard@google.com>2012-08-14 15:11:53 +0900
committerJean Chalard <jchalard@google.com>2012-08-14 17:04:14 +0900
commite30c05800fa463ef622132b0df466f5455281fc1 (patch)
tree83fe94ea086664d9c93e45417a86d0030ed1f324 /java/src/com/android/inputmethod
parent5d6b8e181811e10b38dd30f4ba33757bb2162552 (diff)
downloadlatinime-e30c05800fa463ef622132b0df466f5455281fc1.tar.gz
latinime-e30c05800fa463ef622132b0df466f5455281fc1.tar.xz
latinime-e30c05800fa463ef622132b0df466f5455281fc1.zip
Preemptive anti-deadlock device
We don't know of any actual bug in the implementation of the pool that may result in a deadlock, but this still implements a means out of a deadlock if one ever arises anyway. It's meant to improve the resilience of the spell checker. Bug: 5441027 Change-Id: I689491090792dbb89110ee56631965c5bb2dc712
Diffstat (limited to 'java/src/com/android/inputmethod')
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java4
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java30
2 files changed, 27 insertions, 7 deletions
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 0171dc06d..06f5db749 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -193,7 +193,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
if (shouldFilterOut(inText, mScript)) {
DictAndProximity dictInfo = null;
try {
- dictInfo = mDictionaryPool.takeOrGetNull();
+ dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (null == dictInfo) {
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
}
@@ -236,7 +236,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
boolean isInDict = true;
DictAndProximity dictInfo = null;
try {
- dictInfo = mDictionaryPool.takeOrGetNull();
+ dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (null == dictInfo) {
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index 8fc632ee7..83f82faeb 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -16,14 +16,24 @@
package com.android.inputmethod.latin.spellcheck;
+import android.util.Log;
+
import java.util.Locale;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/**
* A blocking queue that creates dictionaries up to a certain limit as necessary.
+ * As a deadlock-detecting device, if waiting for more than TIMEOUT = 3 seconds, we
+ * will clear the queue and generate its contents again. This is transparent for
+ * the client code, but may help with sloppy clients.
*/
@SuppressWarnings("serial")
public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
+ private final static String TAG = DictionaryPool.class.getSimpleName();
+ // How many seconds we wait for a dictionary to become available. Past this delay, we give up in
+ // fear some bug caused a deadlock, and reset the whole pool.
+ private final static int TIMEOUT = 3;
private final AndroidSpellCheckerService mService;
private final int mMaxSize;
private final Locale mLocale;
@@ -41,13 +51,23 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
}
@Override
- public DictAndProximity take() throws InterruptedException {
+ public DictAndProximity poll(final long timeout, final TimeUnit unit)
+ throws InterruptedException {
final DictAndProximity dict = poll();
if (null != dict) return dict;
synchronized(this) {
if (mSize >= mMaxSize) {
- // Our pool is already full. Wait until some dictionary is ready.
- return super.take();
+ // Our pool is already full. Wait until some dictionary is ready, or TIMEOUT
+ // expires to avoid a deadlock.
+ final DictAndProximity result = super.poll(timeout, unit);
+ if (null == result) {
+ Log.e(TAG, "Deadlock detected ! Resetting dictionary pool");
+ clear();
+ mSize = 1;
+ return mService.createDictAndProximity(mLocale);
+ } else {
+ return result;
+ }
} else {
++mSize;
return mService.createDictAndProximity(mLocale);
@@ -56,9 +76,9 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
}
// Convenience method
- public DictAndProximity takeOrGetNull() {
+ public DictAndProximity pollWithDefaultTimeout() {
try {
- return take();
+ return poll(TIMEOUT, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return null;
}