Merge "Preemptive anti-deadlock device" into jb-mr1-dev
This commit is contained in:
commit
a0cd05842e
2 changed files with 27 additions and 7 deletions
|
@ -193,7 +193,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
|
||||||
if (shouldFilterOut(inText, mScript)) {
|
if (shouldFilterOut(inText, mScript)) {
|
||||||
DictAndProximity dictInfo = null;
|
DictAndProximity dictInfo = null;
|
||||||
try {
|
try {
|
||||||
dictInfo = mDictionaryPool.takeOrGetNull();
|
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
|
||||||
if (null == dictInfo) {
|
if (null == dictInfo) {
|
||||||
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
|
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
|
||||||
boolean isInDict = true;
|
boolean isInDict = true;
|
||||||
DictAndProximity dictInfo = null;
|
DictAndProximity dictInfo = null;
|
||||||
try {
|
try {
|
||||||
dictInfo = mDictionaryPool.takeOrGetNull();
|
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
|
||||||
if (null == dictInfo) {
|
if (null == dictInfo) {
|
||||||
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
|
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,24 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.spellcheck;
|
package com.android.inputmethod.latin.spellcheck;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A blocking queue that creates dictionaries up to a certain limit as necessary.
|
* 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")
|
@SuppressWarnings("serial")
|
||||||
public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
|
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 AndroidSpellCheckerService mService;
|
||||||
private final int mMaxSize;
|
private final int mMaxSize;
|
||||||
private final Locale mLocale;
|
private final Locale mLocale;
|
||||||
|
@ -41,13 +51,23 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DictAndProximity take() throws InterruptedException {
|
public DictAndProximity poll(final long timeout, final TimeUnit unit)
|
||||||
|
throws InterruptedException {
|
||||||
final DictAndProximity dict = poll();
|
final DictAndProximity dict = poll();
|
||||||
if (null != dict) return dict;
|
if (null != dict) return dict;
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (mSize >= mMaxSize) {
|
if (mSize >= mMaxSize) {
|
||||||
// Our pool is already full. Wait until some dictionary is ready.
|
// Our pool is already full. Wait until some dictionary is ready, or TIMEOUT
|
||||||
return super.take();
|
// 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 {
|
} else {
|
||||||
++mSize;
|
++mSize;
|
||||||
return mService.createDictAndProximity(mLocale);
|
return mService.createDictAndProximity(mLocale);
|
||||||
|
@ -56,9 +76,9 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience method
|
// Convenience method
|
||||||
public DictAndProximity takeOrGetNull() {
|
public DictAndProximity pollWithDefaultTimeout() {
|
||||||
try {
|
try {
|
||||||
return take();
|
return poll(TIMEOUT, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue