am e5cfb776: Introduce ExclusiveOwnershipPointer.

* commit 'e5cfb776949eb8b9db8a01191aa1241ac22da0e4':
  Introduce ExclusiveOwnershipPointer.
main
Keisuke Kuroyanagi 2013-10-24 17:38:45 -07:00 committed by Android Git Automerger
commit db917de6aa
13 changed files with 280 additions and 150 deletions

View File

@ -91,7 +91,8 @@ LATIN_IME_CORE_SRC_FILES := \
byte_array_utils.cpp \ byte_array_utils.cpp \
dict_file_writing_utils.cpp \ dict_file_writing_utils.cpp \
forgetting_curve_utils.cpp \ forgetting_curve_utils.cpp \
format_utils.cpp) \ format_utils.cpp \
mmapped_buffer.cpp) \
suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \ suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
$(addprefix suggest/policyimpl/typing/, \ $(addprefix suggest/policyimpl/typing/, \
scoring_params.cpp \ scoring_params.cpp \

View File

@ -86,11 +86,11 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
char sourceDirChars[sourceDirUtf8Length + 1]; char sourceDirChars[sourceDirUtf8Length + 1];
env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars); env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars);
sourceDirChars[sourceDirUtf8Length] = '\0'; sourceDirChars[sourceDirUtf8Length] = '\0';
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy = DictionaryStructureWithBufferPolicy::StructurePoilcyPtr dictionaryStructureWithBufferPolicy(
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy( DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize), sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
isUpdatable == JNI_TRUE); isUpdatable == JNI_TRUE));
if (!dictionaryStructureWithBufferPolicy) { if (!dictionaryStructureWithBufferPolicy.get()) {
return 0; return 0;
} }

View File

@ -21,9 +21,7 @@
#include <stdint.h> #include <stdint.h>
#include "defines.h" #include "defines.h"
#include "suggest/core/dictionary/bigram_dictionary.h"
#include "suggest/core/policy/dictionary_header_structure_policy.h" #include "suggest/core/policy/dictionary_header_structure_policy.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
#include "suggest/core/session/dic_traverse_session.h" #include "suggest/core/session/dic_traverse_session.h"
#include "suggest/core/suggest.h" #include "suggest/core/suggest.h"
#include "suggest/core/suggest_options.h" #include "suggest/core/suggest_options.h"
@ -35,22 +33,15 @@ namespace latinime {
const int Dictionary::HEADER_ATTRIBUTE_BUFFER_SIZE = 32; const int Dictionary::HEADER_ATTRIBUTE_BUFFER_SIZE = 32;
Dictionary::Dictionary(JNIEnv *env, Dictionary::Dictionary(JNIEnv *env, const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy) &dictionaryStructureWithBufferPolicy)
: mDictionaryStructureWithBufferPolicy(dictionaryStructureWithBufferPolicy), : mDictionaryStructureWithBufferPolicy(dictionaryStructureWithBufferPolicy),
mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy)), mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy.get())),
mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())), mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) { mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
logDictionaryInfo(env); logDictionaryInfo(env);
} }
Dictionary::~Dictionary() {
delete mBigramDictionary;
delete mGestureSuggest;
delete mTypingSuggest;
delete mDictionaryStructureWithBufferPolicy;
}
int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession, int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint, int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
@ -60,7 +51,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
if (suggestOptions->isGesture()) { if (suggestOptions->isGesture()) {
DicTraverseSession::initSessionInstance( DicTraverseSession::initSessionInstance(
traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions); traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates, result = mGestureSuggest.get()->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords, ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
frequencies, spaceIndices, outputTypes, outputAutoCommitFirstWordConfidence); frequencies, spaceIndices, outputTypes, outputAutoCommitFirstWordConfidence);
if (DEBUG_DICT) { if (DEBUG_DICT) {
@ -70,7 +61,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
} else { } else {
DicTraverseSession::initSessionInstance( DicTraverseSession::initSessionInstance(
traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions); traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates, result = mTypingSuggest.get()->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
outWords, frequencies, spaceIndices, outputTypes, outWords, frequencies, spaceIndices, outputTypes,
outputAutoCommitFirstWordConfidence); outputAutoCommitFirstWordConfidence);
@ -84,7 +75,8 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
int Dictionary::getBigrams(const int *word, int length, int *outWords, int *frequencies, int Dictionary::getBigrams(const int *word, int length, int *outWords, int *frequencies,
int *outputTypes) const { int *outputTypes) const {
if (length <= 0) return 0; if (length <= 0) return 0;
return mBigramDictionary->getPredictions(word, length, outWords, frequencies, outputTypes); return mBigramDictionary.get()->getPredictions(word, length, outWords, frequencies,
outputTypes);
} }
int Dictionary::getProbability(const int *word, int length) const { int Dictionary::getProbability(const int *word, int length) const {
@ -98,39 +90,39 @@ int Dictionary::getProbability(const int *word, int length) const {
int Dictionary::getBigramProbability(const int *word0, int length0, const int *word1, int Dictionary::getBigramProbability(const int *word0, int length0, const int *word1,
int length1) const { int length1) const {
return mBigramDictionary->getBigramProbability(word0, length0, word1, length1); return mBigramDictionary.get()->getBigramProbability(word0, length0, word1, length1);
} }
void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) { void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) {
mDictionaryStructureWithBufferPolicy->addUnigramWord(word, length, probability); mDictionaryStructureWithBufferPolicy.get()->addUnigramWord(word, length, probability);
} }
void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1, void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1, const int probability) { const int length1, const int probability) {
mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, word1, length1, mDictionaryStructureWithBufferPolicy.get()->addBigramWords(word0, length0, word1, length1,
probability); probability);
} }
void Dictionary::removeBigramWords(const int *const word0, const int length0, void Dictionary::removeBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1) { const int *const word1, const int length1) {
mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1); mDictionaryStructureWithBufferPolicy.get()->removeBigramWords(word0, length0, word1, length1);
} }
void Dictionary::flush(const char *const filePath) { void Dictionary::flush(const char *const filePath) {
mDictionaryStructureWithBufferPolicy->flush(filePath); mDictionaryStructureWithBufferPolicy.get()->flush(filePath);
} }
void Dictionary::flushWithGC(const char *const filePath) { void Dictionary::flushWithGC(const char *const filePath) {
mDictionaryStructureWithBufferPolicy->flushWithGC(filePath); mDictionaryStructureWithBufferPolicy.get()->flushWithGC(filePath);
} }
bool Dictionary::needsToRunGC(const bool mindsBlockByGC) { bool Dictionary::needsToRunGC(const bool mindsBlockByGC) {
return mDictionaryStructureWithBufferPolicy->needsToRunGC(mindsBlockByGC); return mDictionaryStructureWithBufferPolicy.get()->needsToRunGC(mindsBlockByGC);
} }
void Dictionary::getProperty(const char *const query, char *const outResult, void Dictionary::getProperty(const char *const query, char *const outResult,
const int maxResultLength) { const int maxResultLength) {
return mDictionaryStructureWithBufferPolicy->getProperty(query, outResult, maxResultLength); return mDictionaryStructureWithBufferPolicy.get()->getProperty(query, outResult, maxResultLength);
} }
void Dictionary::logDictionaryInfo(JNIEnv *const env) const { void Dictionary::logDictionaryInfo(JNIEnv *const env) const {

View File

@ -21,14 +21,16 @@
#include "defines.h" #include "defines.h"
#include "jni.h" #include "jni.h"
#include "suggest/core/dictionary/bigram_dictionary.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
#include "suggest/core/suggest_interface.h"
#include "utils/exclusive_ownership_pointer.h"
namespace latinime { namespace latinime {
class BigramDictionary;
class DictionaryStructureWithBufferPolicy; class DictionaryStructureWithBufferPolicy;
class DicTraverseSession; class DicTraverseSession;
class ProximityInfo; class ProximityInfo;
class SuggestInterface;
class SuggestOptions; class SuggestOptions;
class Dictionary { class Dictionary {
@ -53,8 +55,8 @@ class Dictionary {
static const int KIND_FLAG_POSSIBLY_OFFENSIVE = 0x80000000; static const int KIND_FLAG_POSSIBLY_OFFENSIVE = 0x80000000;
static const int KIND_FLAG_EXACT_MATCH = 0x40000000; static const int KIND_FLAG_EXACT_MATCH = 0x40000000;
Dictionary(JNIEnv *env, Dictionary(JNIEnv *env, const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPoilcy); &dictionaryStructureWithBufferPoilcy);
int getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession, int getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
@ -87,20 +89,22 @@ class Dictionary {
const int maxResultLength); const int maxResultLength);
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const { const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
return mDictionaryStructureWithBufferPolicy; return mDictionaryStructureWithBufferPolicy.get();
} }
virtual ~Dictionary();
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary); DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
typedef ExclusiveOwnershipPointer<BigramDictionary> BigramDictionaryPtr;
typedef ExclusiveOwnershipPointer<SuggestInterface> SuggestInterfacePtr;
static const int HEADER_ATTRIBUTE_BUFFER_SIZE; static const int HEADER_ATTRIBUTE_BUFFER_SIZE;
DictionaryStructureWithBufferPolicy *const mDictionaryStructureWithBufferPolicy; const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
const BigramDictionary *const mBigramDictionary; mDictionaryStructureWithBufferPolicy;
const SuggestInterface *const mGestureSuggest; const BigramDictionaryPtr mBigramDictionary;
const SuggestInterface *const mTypingSuggest; const SuggestInterfacePtr mGestureSuggest;
const SuggestInterfacePtr mTypingSuggest;
void logDictionaryInfo(JNIEnv *const env) const; void logDictionaryInfo(JNIEnv *const env) const;
}; };

View File

@ -18,6 +18,7 @@
#define LATINIME_DICTIONARY_STRUCTURE_POLICY_H #define LATINIME_DICTIONARY_STRUCTURE_POLICY_H
#include "defines.h" #include "defines.h"
#include "utils/exclusive_ownership_pointer.h"
namespace latinime { namespace latinime {
@ -33,6 +34,8 @@ class DictionaryShortcutsStructurePolicy;
*/ */
class DictionaryStructureWithBufferPolicy { class DictionaryStructureWithBufferPolicy {
public: public:
typedef ExclusiveOwnershipPointer<DictionaryStructureWithBufferPolicy> StructurePoilcyPtr;
virtual ~DictionaryStructureWithBufferPolicy() {} virtual ~DictionaryStructureWithBufferPolicy() {}
virtual int getRootPosition() const = 0; virtual int getRootPosition() const = 0;

View File

@ -26,30 +26,32 @@
namespace latinime { namespace latinime {
/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory /* static */ DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
::newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset, DictionaryStructureWithBufferPolicyFactory
const int size, const bool isUpdatable) { ::newDictionaryStructureWithBufferPolicy(const char *const path,
// Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of const int bufOffset, const int size, const bool isUpdatable) {
// impl classes of DictionaryStructureWithBufferPolicy. // Allocated buffer in MmapedBuffer::newBuffer() will be freed in the destructor of
const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, bufOffset, size, // MmappedBufferWrapper if the instance has the responsibility.
isUpdatable); MmappedBuffer::MmappedBufferPtr mmappedBuffer(MmappedBuffer::openBuffer(path, bufOffset, size,
if (!mmapedBuffer) { isUpdatable));
return 0; if (!mmappedBuffer.get()) {
return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
} }
switch (FormatUtils::detectFormatVersion(mmapedBuffer->getBuffer(), switch (FormatUtils::detectFormatVersion(mmappedBuffer.get()->getBuffer(),
mmapedBuffer->getBufferSize())) { mmappedBuffer.get()->getBufferSize())) {
case FormatUtils::VERSION_2: case FormatUtils::VERSION_2:
return new PatriciaTriePolicy(mmapedBuffer); return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(
new PatriciaTriePolicy(mmappedBuffer));
case FormatUtils::VERSION_3: case FormatUtils::VERSION_3:
return new DynamicPatriciaTriePolicy(mmapedBuffer); return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(
new DynamicPatriciaTriePolicy(mmappedBuffer));
case FormatUtils::VERSION_4: case FormatUtils::VERSION_4:
// TODO: Support version 4 dictionary format. // TODO: Support version 4 dictionary format.
// Fall through. // Fall through.
default: default:
AKLOGE("DICT: dictionary format is unknown, bad magic number"); AKLOGE("DICT: dictionary format is unknown, bad magic number");
delete mmapedBuffer;
ASSERT(false); ASSERT(false);
return 0; return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
} }
} }

View File

@ -21,13 +21,15 @@
#include "defines.h" #include "defines.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
#include "utils/exclusive_ownership_pointer.h"
namespace latinime { namespace latinime {
class DictionaryStructureWithBufferPolicyFactory { class DictionaryStructureWithBufferPolicyFactory {
public: public:
static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy( static DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
const char *const path, const int bufOffset, const int size, const bool isUpdatable); newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
const int size, const bool isUpdatable);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory); DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);

View File

@ -34,16 +34,14 @@ class DicNodeVector;
class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
public: public:
PatriciaTriePolicy(const MmappedBuffer *const buffer) PatriciaTriePolicy(const MmappedBuffer::MmappedBufferPtr &mmappedBuffer)
: mBuffer(buffer), mHeaderPolicy(mBuffer->getBuffer(), FormatUtils::VERSION_2), : mMmappedBuffer(mmappedBuffer),
mDictRoot(mBuffer->getBuffer() + mHeaderPolicy.getSize()), mHeaderPolicy(mMmappedBuffer.get()->getBuffer(), FormatUtils::VERSION_2),
mDictBufferSize(mBuffer->getBufferSize() - mHeaderPolicy.getSize()), mDictRoot(mMmappedBuffer.get()->getBuffer() + mHeaderPolicy.getSize()),
mDictBufferSize(mMmappedBuffer.get()->getBufferSize()
- mHeaderPolicy.getSize()),
mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot) {} mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot) {}
~PatriciaTriePolicy() {
delete mBuffer;
}
AK_FORCE_INLINE int getRootPosition() const { AK_FORCE_INLINE int getRootPosition() const {
return 0; return 0;
} }
@ -125,7 +123,7 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy); DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
const MmappedBuffer *const mBuffer; const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
const HeaderPolicy mHeaderPolicy; const HeaderPolicy mHeaderPolicy;
const uint8_t *const mDictRoot; const uint8_t *const mDictRoot;
const int mDictBufferSize; const int mDictBufferSize;

View File

@ -216,7 +216,7 @@ int DynamicPatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) c
bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int length, bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int length,
const int probability) { const int probability) {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: addUnigramWord() is called for non-updatable dictionary."); AKLOGI("Warning: addUnigramWord() is called for non-updatable dictionary.");
return false; return false;
} }
@ -244,7 +244,7 @@ bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int
bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int length0, bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1, const int probability) { const int *const word1, const int length1, const int probability) {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary."); AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
return false; return false;
} }
@ -278,7 +278,7 @@ bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int
bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0, bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1) { const int *const word1, const int length1) {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: removeBigramWords() is called for non-updatable dictionary."); AKLOGI("Warning: removeBigramWords() is called for non-updatable dictionary.");
return false; return false;
} }
@ -308,7 +308,7 @@ bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const
} }
void DynamicPatriciaTriePolicy::flush(const char *const filePath) { void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: flush() is called for non-updatable dictionary."); AKLOGI("Warning: flush() is called for non-updatable dictionary.");
return; return;
} }
@ -318,7 +318,7 @@ void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
} }
void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) { void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary."); AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
return; return;
} }
@ -334,7 +334,7 @@ void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
} }
bool DynamicPatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const { bool DynamicPatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
if (!mBuffer->isUpdatable()) { if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary."); AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
return false; return false;
} }

View File

@ -33,21 +33,20 @@ class DicNodeVector;
class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
public: public:
DynamicPatriciaTriePolicy(const MmappedBuffer *const buffer) DynamicPatriciaTriePolicy(const MmappedBuffer::MmappedBufferPtr &mmappedBuffer)
: mBuffer(buffer), mHeaderPolicy(mBuffer->getBuffer(), FormatUtils::VERSION_3), : mMmappedBuffer(mmappedBuffer),
mBufferWithExtendableBuffer(mBuffer->getBuffer() + mHeaderPolicy.getSize(), mHeaderPolicy(mMmappedBuffer.get()->getBuffer(), FormatUtils::VERSION_3),
mBuffer->getBufferSize() - mHeaderPolicy.getSize(), mBufferWithExtendableBuffer(mMmappedBuffer.get()->getBuffer()
BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), + mHeaderPolicy.getSize(), mMmappedBuffer.get()->getBufferSize()
- mHeaderPolicy.getSize(),
BufferWithExtendableBuffer
::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
mShortcutListPolicy(&mBufferWithExtendableBuffer), mShortcutListPolicy(&mBufferWithExtendableBuffer),
mBigramListPolicy(&mHeaderPolicy, &mBufferWithExtendableBuffer, &mShortcutListPolicy, mBigramListPolicy(&mHeaderPolicy, &mBufferWithExtendableBuffer, &mShortcutListPolicy,
mHeaderPolicy.isDecayingDict()), mHeaderPolicy.isDecayingDict()),
mUnigramCount(mHeaderPolicy.getUnigramCount()), mUnigramCount(mHeaderPolicy.getUnigramCount()),
mBigramCount(mHeaderPolicy.getBigramCount()), mNeedsToDecayForTesting(false) {} mBigramCount(mHeaderPolicy.getBigramCount()), mNeedsToDecayForTesting(false) {}
~DynamicPatriciaTriePolicy() {
delete mBuffer;
}
AK_FORCE_INLINE int getRootPosition() const { AK_FORCE_INLINE int getRootPosition() const {
return 0; return 0;
} }
@ -110,7 +109,7 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
static const int MAX_DICT_EXTENDED_REGION_SIZE; static const int MAX_DICT_EXTENDED_REGION_SIZE;
static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS; static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
const MmappedBuffer *const mBuffer; const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
const HeaderPolicy mHeaderPolicy; const HeaderPolicy mHeaderPolicy;
BufferWithExtendableBuffer mBufferWithExtendableBuffer; BufferWithExtendableBuffer mBufferWithExtendableBuffer;
DynamicShortcutListPolicy mShortcutListPolicy; DynamicShortcutListPolicy mShortcutListPolicy;

View File

@ -0,0 +1,99 @@
/*
* 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.
*/
#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
#include <cerrno>
#include <climits>
#include <cstdio>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "suggest/policyimpl/dictionary/utils/file_utils.h"
namespace latinime {
/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
const char *const path, const int bufferOffset, const int bufferSize,
const bool isUpdatable) {
const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
const int mmapFd = open(path, openMode);
if (mmapFd < 0) {
AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
return MmappedBufferPtr(0);
}
const int pagesize = getpagesize();
const int offset = bufferOffset % pagesize;
int alignedOffset = bufferOffset - offset;
int alignedSize = bufferSize + offset;
const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
alignedOffset);
if (mmappedBuffer == MAP_FAILED) {
AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
close(mmapFd);
return MmappedBufferPtr(0);
}
uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
if (!buffer) {
AKLOGE("DICT: buffer is null");
close(mmapFd);
return MmappedBufferPtr(0);
}
return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
mmapFd, isUpdatable));
}
/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
const char *const path, const bool isUpdatable) {
const int fileSize = FileUtils::getFileSize(path);
if (fileSize == -1) {
return MmappedBufferPtr(0);
} else if (fileSize == 0) {
return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
} else {
return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
}
}
/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
const char *const dirPath, const char *const fileName, const bool isUpdatable) {
const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
char filePath[filePathBufferSize];
const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
fileName);
if (filePathLength >= filePathBufferSize) {
return 0;
}
return openBuffer(filePath, isUpdatable);
}
MmappedBuffer::~MmappedBuffer() {
if (mAlignedSize == 0) {
return;
}
int ret = munmap(mMmappedBuffer, mAlignedSize);
if (ret != 0) {
AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
}
ret = close(mMmapFd);
if (ret != 0) {
AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
}
}
} // namespace latinime

View File

@ -17,88 +17,27 @@
#ifndef LATINIME_MMAPPED_BUFFER_H #ifndef LATINIME_MMAPPED_BUFFER_H
#define LATINIME_MMAPPED_BUFFER_H #define LATINIME_MMAPPED_BUFFER_H
#include <cerrno>
#include <climits>
#include <cstdio>
#include <fcntl.h>
#include <stdint.h> #include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
#include "defines.h" #include "defines.h"
#include "suggest/policyimpl/dictionary/utils/file_utils.h" #include "utils/exclusive_ownership_pointer.h"
namespace latinime { namespace latinime {
class MmappedBuffer { class MmappedBuffer {
public: public:
static MmappedBuffer *openBuffer(const char *const path, const int bufferOffset, typedef ExclusiveOwnershipPointer<MmappedBuffer> MmappedBufferPtr;
const int bufferSize, const bool isUpdatable) {
const int openMode = isUpdatable ? O_RDWR : O_RDONLY; static MmappedBufferPtr openBuffer(const char *const path,
const int mmapFd = open(path, openMode); const int bufferOffset, const int bufferSize, const bool isUpdatable);
if (mmapFd < 0) {
AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
return 0;
}
const int pagesize = getpagesize();
const int offset = bufferOffset % pagesize;
int alignedOffset = bufferOffset - offset;
int alignedSize = bufferSize + offset;
const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
alignedOffset);
if (mmappedBuffer == MAP_FAILED) {
AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
close(mmapFd);
return 0;
}
uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
if (!buffer) {
AKLOGE("DICT: buffer is null");
close(mmapFd);
return 0;
}
return new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize, mmapFd,
isUpdatable);
}
// Mmap entire file. // Mmap entire file.
static MmappedBuffer *openBuffer(const char *const path, const bool isUpdatable) { static MmappedBufferPtr openBuffer(const char *const path, const bool isUpdatable);
const int fileSize = FileUtils::getFileSize(path);
if (fileSize == -1) {
return 0;
} else if (fileSize == 0) {
return new MmappedBuffer(isUpdatable);
} else {
return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
}
}
static MmappedBuffer *openBuffer(const char *const dirPath, const char *const fileName, static MmappedBufferPtr openBuffer(const char *const dirPath, const char *const fileName,
const bool isUpdatable) { const bool isUpdatable);
const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
char filePath[filePathBufferSize];
const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
fileName);
if (filePathLength >= filePathBufferSize) {
return 0;
}
return openBuffer(filePath, isUpdatable);
}
~MmappedBuffer() { ~MmappedBuffer();
if (mAlignedSize == 0) {
return;
}
int ret = munmap(mMmappedBuffer, mAlignedSize);
if (ret != 0) {
AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
}
ret = close(mMmapFd);
if (ret != 0) {
AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
}
}
AK_FORCE_INLINE uint8_t *getBuffer() const { AK_FORCE_INLINE uint8_t *getBuffer() const {
return mBuffer; return mBuffer;

View File

@ -0,0 +1,91 @@
/*
* 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.
*/
#ifndef LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H
#define LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H
#include "defines.h"
namespace latinime {
template<class T>
class ExclusiveOwnershipPointer {
public:
// This instance become an owner of the raw pointer.
ExclusiveOwnershipPointer(T *const rawPointer)
: mPointer(rawPointer),
mSharedOwnerPtr(new (ExclusiveOwnershipPointer<T> *)(this)) {}
// Move the ownership.
ExclusiveOwnershipPointer(const ExclusiveOwnershipPointer<T> &pointer)
: mPointer(pointer.mPointer), mSharedOwnerPtr(pointer.mSharedOwnerPtr) {
transferOwnership(&pointer);
}
~ExclusiveOwnershipPointer() {
deletePointersIfHavingOwnership();
}
// Move the ownership.
ExclusiveOwnershipPointer<T> &operator=(const ExclusiveOwnershipPointer<T> &pointer) {
// Delete pointers when this is an owner of another pointer.
deletePointersIfHavingOwnership();
mPointer = pointer.mPointer;
mSharedOwnerPtr = pointer.mSharedOwnerPtr;
transferOwnership(pointer);
return *this;
}
T *get() const {
return mPointer;
}
private:
// This class allows to copy and assign and ensures only one instance has the ownership of the
// managed pointer.
ExclusiveOwnershipPointer() : mPointer(0), mSharedOwnerPtr(0) {}
void transferOwnership(const ExclusiveOwnershipPointer<T> *const src) {
if (*mSharedOwnerPtr != src) {
AKLOGE("Failed to transfer the ownership because src is not the current owner."
"src: %p, owner: %p", src, *mSharedOwnerPtr);
ASSERT(false);
return;
}
// Transfer the ownership from src to this instance.
*mSharedOwnerPtr = this;
}
void deletePointersIfHavingOwnership() {
if (mSharedOwnerPtr && *mSharedOwnerPtr == this) {
if (mPointer) {
if (DEBUG_DICT) {
AKLOGI("Releasing pointer: %p", mPointer);
}
delete mPointer;
}
delete mSharedOwnerPtr;
}
}
T *mPointer;
// mSharedOwnerPtr points a shared memory space where the instance which has the ownership is
// stored.
ExclusiveOwnershipPointer<T> **mSharedOwnerPtr;
};
} // namespace latinime
#endif /* LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H */