Use reentrant lock for main dictionaries. DO NOT MERGE

cherrypick of Iaa9b79fc770d8ae2ec9d7c362c90c28bc9f65ea8

Bug: 10964805
Change-Id: Id5e67b00bf9594be0591c87407a78146297e0e78
This commit is contained in:
Keisuke Kuroyanagi 2013-09-30 18:16:29 +09:00 committed by Ken Wakasa
parent ceb364c041
commit e628cd3c32
2 changed files with 135 additions and 16 deletions

View file

@ -51,7 +51,7 @@ public final class DictionaryFactory {
if (null == locale) { if (null == locale) {
Log.e(TAG, "No locale defined for dictionary"); Log.e(TAG, "No locale defined for dictionary");
return new DictionaryCollection(Dictionary.TYPE_MAIN, return new DictionaryCollection(Dictionary.TYPE_MAIN,
createBinaryDictionary(context, locale)); createReadOnlyBinaryDictionary(context, locale));
} }
final LinkedList<Dictionary> dictList = CollectionUtils.newLinkedList(); final LinkedList<Dictionary> dictList = CollectionUtils.newLinkedList();
@ -59,11 +59,11 @@ public final class DictionaryFactory {
BinaryDictionaryGetter.getDictionaryFiles(locale, context); BinaryDictionaryGetter.getDictionaryFiles(locale, context);
if (null != assetFileList) { if (null != assetFileList) {
for (final AssetFileAddress f : assetFileList) { for (final AssetFileAddress f : assetFileList) {
final BinaryDictionary binaryDictionary = new BinaryDictionary(f.mFilename, final ReadOnlyBinaryDictionary readOnlyBinaryDictionary =
f.mOffset, f.mLength, useFullEditDistance, locale, Dictionary.TYPE_MAIN, new ReadOnlyBinaryDictionary(f.mFilename, f.mOffset, f.mLength,
false /* isUpdatable */); useFullEditDistance, locale, Dictionary.TYPE_MAIN);
if (binaryDictionary.isValidDictionary()) { if (readOnlyBinaryDictionary.isValidDictionary()) {
dictList.add(binaryDictionary); dictList.add(readOnlyBinaryDictionary);
} }
} }
} }
@ -89,12 +89,12 @@ public final class DictionaryFactory {
} }
/** /**
* Initializes a dictionary from a raw resource file * Initializes a read-only binary dictionary from a raw resource file
* @param context application context for reading resources * @param context application context for reading resources
* @param locale the locale to use for the resource * @param locale the locale to use for the resource
* @return an initialized instance of BinaryDictionary * @return an initialized instance of ReadOnlyBinaryDictionary
*/ */
protected static BinaryDictionary createBinaryDictionary(final Context context, protected static ReadOnlyBinaryDictionary createReadOnlyBinaryDictionary(final Context context,
final Locale locale) { final Locale locale) {
AssetFileDescriptor afd = null; AssetFileDescriptor afd = null;
try { try {
@ -113,9 +113,8 @@ public final class DictionaryFactory {
Log.e(TAG, "sourceDir is not a file: " + sourceDir); Log.e(TAG, "sourceDir is not a file: " + sourceDir);
return null; return null;
} }
return new BinaryDictionary(sourceDir, afd.getStartOffset(), afd.getLength(), return new ReadOnlyBinaryDictionary(sourceDir, afd.getStartOffset(), afd.getLength(),
false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN, false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN);
false /* isUpdatable */);
} catch (android.content.res.Resources.NotFoundException e) { } catch (android.content.res.Resources.NotFoundException e) {
Log.e(TAG, "Could not find the resource"); Log.e(TAG, "Could not find the resource");
return null; return null;
@ -142,10 +141,10 @@ public final class DictionaryFactory {
final DictionaryCollection dictionaryCollection = final DictionaryCollection dictionaryCollection =
new DictionaryCollection(Dictionary.TYPE_MAIN); new DictionaryCollection(Dictionary.TYPE_MAIN);
for (final AssetFileAddress address : dictionaryList) { for (final AssetFileAddress address : dictionaryList) {
final BinaryDictionary binaryDictionary = new BinaryDictionary(address.mFilename, final ReadOnlyBinaryDictionary readOnlyBinaryDictionary = new ReadOnlyBinaryDictionary(
address.mOffset, address.mLength, useFullEditDistance, locale, address.mFilename, address.mOffset, address.mLength, useFullEditDistance,
Dictionary.TYPE_MAIN, false /* isUpdatable */); locale, Dictionary.TYPE_MAIN);
dictionaryCollection.addDictionary(binaryDictionary); dictionaryCollection.addDictionary(readOnlyBinaryDictionary);
} }
return dictionaryCollection; return dictionaryCollection;
} }

View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This class provides binary dictionary reading operations with locking. An instance of this class
* can be used by multiple threads. Note that different session IDs must be used when multiple
* threads get suggestions using this class.
*/
public final class ReadOnlyBinaryDictionary extends Dictionary {
/**
* A lock for accessing binary dictionary. Only closing binary dictionary is the operation
* that change the state of dictionary.
*/
private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
private final BinaryDictionary mBinaryDictionary;
public ReadOnlyBinaryDictionary(final String filename, final long offset, final long length,
final boolean useFullEditDistance, final Locale locale, final String dictType) {
super(dictType);
mBinaryDictionary = new BinaryDictionary(filename, offset, length, useFullEditDistance,
locale, dictType, false /* isUpdatable */);
}
public boolean isValidDictionary() {
return mBinaryDictionary.isValidDictionary();
}
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
additionalFeaturesOptions, 0 /* sessionId */);
}
@Override
public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
final int sessionId) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.getSuggestions(composer, prevWord, proximityInfo,
blockOffensiveWords, additionalFeaturesOptions);
} finally {
mLock.readLock().unlock();
}
}
return null;
}
@Override
public boolean isValidWord(final String word) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.isValidWord(word);
} finally {
mLock.readLock().unlock();
}
}
return false;
}
@Override
public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.shouldAutoCommit(candidate);
} finally {
mLock.readLock().unlock();
}
}
return false;
}
@Override
public int getFrequency(final String word) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.getFrequency(word);
} finally {
mLock.readLock().unlock();
}
}
return NOT_A_PROBABILITY;
}
@Override
public void close() {
mLock.writeLock().lock();
try {
mBinaryDictionary.close();
} finally {
mLock.writeLock().unlock();
}
}
}