Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0cd0584 authored by Jean Chalard's avatar Jean Chalard Committed by Android (Google) Code Review
Browse files

Merge "Preemptive anti-deadlock device" into jb-mr1-dev

parents d832bec4 e30c0580
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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();
                }
+25 −5
Original line number Diff line number Diff line
@@ -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;
        }