am a0cd0584: Merge "Preemptive anti-deadlock device" into jb-mr1-dev

* commit 'a0cd05842e26e802121823a25274190f65a2450f':
  Preemptive anti-deadlock device
This commit is contained in:
Jean Chalard 2012-08-14 01:11:22 -07:00 committed by Android Git Automerger
commit 4de3bc305b
2 changed files with 27 additions and 7 deletions

View file

@ -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();
}

View file

@ -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;
}