am a0cd0584
: Merge "Preemptive anti-deadlock device" into jb-mr1-dev
* commit 'a0cd05842e26e802121823a25274190f65a2450f': Preemptive anti-deadlock device
This commit is contained in:
commit
4de3bc305b
2 changed files with 27 additions and 7 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue