Skip to content
Snippets Groups Projects
Commit 94c7bd47 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi Committed by Android (Google) Code Review
Browse files

Merge "Separate DicNodePool from DicNodePriorityQueue."

parents 65a199ca 67ff21f3
No related branches found
No related tags found
No related merge requests found
......@@ -24,8 +24,7 @@ DicNode::DicNode(const DicNode &dicNode)
mProfiler(dicNode.mProfiler),
#endif
mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed),
mReleaseListener(nullptr) {
mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion) {
/* empty */
}
......@@ -36,8 +35,6 @@ DicNode &DicNode::operator=(const DicNode &dicNode) {
mDicNodeProperties = dicNode.mDicNodeProperties;
mDicNodeState = dicNode.mDicNodeState;
mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
mIsUsed = dicNode.mIsUsed;
mReleaseListener = dicNode.mReleaseListener;
return *this;
}
......
......@@ -19,7 +19,6 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node_profiler.h"
#include "suggest/core/dicnode/dic_node_release_listener.h"
#include "suggest/core/dicnode/dic_node_utils.h"
#include "suggest/core/dicnode/internal/dic_node_state.h"
#include "suggest/core/dicnode/internal/dic_node_properties.h"
......@@ -89,8 +88,7 @@ class DicNode {
#if DEBUG_DICT
mProfiler(),
#endif
mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false),
mIsUsed(false), mReleaseListener(nullptr) {}
mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {}
DicNode(const DicNode &dicNode);
DicNode &operator=(const DicNode &dicNode);
......@@ -98,7 +96,6 @@ class DicNode {
// Init for copy
void initByCopy(const DicNode *const dicNode) {
mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
mDicNodeState.initByCopy(&dicNode->mDicNodeState);
......@@ -107,7 +104,6 @@ class DicNode {
// Init for root with prevWordPtNodePos which is used for bigram
void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
mIsUsed = true;
mIsCachedForNextSuggestion = false;
mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos);
mDicNodeState.init();
......@@ -116,7 +112,6 @@ class DicNode {
// Init for root with previous word
void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos());
mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
......@@ -125,7 +120,6 @@ class DicNode {
}
void initAsPassingChild(DicNode *parentDicNode) {
mIsUsed = true;
mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
......@@ -137,7 +131,6 @@ class DicNode {
const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
const bool hasChildren, const bool isBlacklistedOrNotAWord,
const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
mIsUsed = true;
uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
const uint16_t newLeavingDepth = static_cast<uint16_t>(
......@@ -150,17 +143,6 @@ class DicNode {
PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
}
AK_FORCE_INLINE void finalize() {
mIsUsed = false;
if (mReleaseListener) {
mReleaseListener->onReleased(this);
}
}
bool isUsed() const {
return mIsUsed;
}
bool isRoot() const {
return getNodeCodePointCount() == 0;
}
......@@ -466,10 +448,6 @@ class DicNode {
#endif
}
void setReleaseListener(DicNodeReleaseListener *releaseListener) {
mReleaseListener = releaseListener;
}
AK_FORCE_INLINE bool compare(const DicNode *right) const {
// Promote exact matches to prevent them from being pruned.
const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
......@@ -507,8 +485,6 @@ class DicNode {
DicNodeState mDicNodeState;
// TODO: Remove
bool mIsCachedForNextSuggestion;
bool mIsUsed;
DicNodeReleaseListener *mReleaseListener;
AK_FORCE_INLINE int getTotalInputIndex() const {
int index = 0;
......
/*
* Copyright (C) 2014 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_DIC_NODE_POOL_H
#define LATINIME_DIC_NODE_POOL_H
#include <deque>
#include <unordered_set>
#include <vector>
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
namespace latinime {
class DicNodePool {
public:
explicit DicNodePool(const int capacity) : mDicNodes(), mPooledDicNodes() {
reset(capacity);
}
void reset(const int capacity) {
if (capacity == static_cast<int>(mDicNodes.size())
&& capacity == static_cast<int>(mPooledDicNodes.size())) {
// No need to reset.
return;
}
mDicNodes.resize(capacity);
mDicNodes.shrink_to_fit();
mPooledDicNodes.clear();
for (auto &dicNode : mDicNodes) {
mPooledDicNodes.emplace_back(&dicNode);
}
}
// Get a DicNode instance from the pool. The instance has to be returned by returnInstance().
DicNode *getInstance() {
if (mPooledDicNodes.empty()) {
return nullptr;
}
DicNode *const dicNode = mPooledDicNodes.back();
mPooledDicNodes.pop_back();
return dicNode;
}
// Return an instance that has been removed from the pool by getInstance() to the pool. The
// instance must not be used after returning without getInstance().
void placeBackInstance(DicNode *dicNode) {
mPooledDicNodes.emplace_back(dicNode);
}
void dump() const {
AKLOGI("\n\n\n\n\n===========================");
std::unordered_set<const DicNode*> usedDicNodes;
for (const auto &dicNode : mDicNodes) {
usedDicNodes.insert(&dicNode);
}
for (const auto &dicNodePtr : mPooledDicNodes) {
usedDicNodes.erase(dicNodePtr);
}
for (const auto &usedDicNodePtr : usedDicNodes) {
usedDicNodePtr->dump("DIC_NODE_POOL: ");
}
AKLOGI("===========================\n\n\n\n\n");
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePool);
std::vector<DicNode> mDicNodes;
std::deque<DicNode*> mPooledDicNodes;
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_POOL_H
......@@ -23,38 +23,30 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
#include "suggest/core/dicnode/dic_node_release_listener.h"
#include "suggest/core/dicnode/dic_node_pool.h"
namespace latinime {
class DicNodePriorityQueue : public DicNodeReleaseListener {
class DicNodePriorityQueue {
public:
AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
: mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(),
mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() {
mDicNodesBuf.resize(mCapacity + 1);
mUnusedNodeIndices.resize(mCapacity + 1);
clearAndResizeToCapacity();
: mMaxSize(capacity), mDicNodesQueue(), mDicNodePool(capacity) {
clear();
}
// Non virtual inline destructor -- never inherit this class
AK_FORCE_INLINE ~DicNodePriorityQueue() {}
int getSize() const {
AK_FORCE_INLINE int getSize() const {
return static_cast<int>(mDicNodesQueue.size());
}
int getMaxSize() const {
AK_FORCE_INLINE int getMaxSize() const {
return mMaxSize;
}
AK_FORCE_INLINE void setMaxSize(const int maxSize) {
ASSERT(maxSize <= mCapacity);
mMaxSize = std::min(maxSize, mCapacity);
}
AK_FORCE_INLINE void clearAndResizeToCapacity() {
clearAndResize(mCapacity);
mMaxSize = maxSize;
}
AK_FORCE_INLINE void clear() {
......@@ -62,25 +54,32 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
}
AK_FORCE_INLINE void clearAndResize(const int maxSize) {
ASSERT(maxSize <= mCapacity);
mMaxSize = maxSize;
while (!mDicNodesQueue.empty()) {
mDicNodesQueue.pop();
}
setMaxSize(maxSize);
for (int i = 0; i < mCapacity + 1; ++i) {
mDicNodesBuf[i].finalize();
mDicNodesBuf[i].setReleaseListener(this);
mUnusedNodeIndices[i] = (i == mCapacity) ? NOT_A_NODE_ID : (i + 1);
}
mNextUnusedNodeId = 0;
mDicNodePool.reset(mMaxSize + 1);
}
// Copy
AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) {
return copyPush(dicNode, mMaxSize);
AK_FORCE_INLINE void copyPush(const DicNode *const dicNode) {
DicNode *const pooledDicNode = newDicNode(dicNode);
if (!pooledDicNode) {
return;
}
if (getSize() < mMaxSize) {
mDicNodesQueue.push(pooledDicNode);
return;
}
if (betterThanWorstDicNode(pooledDicNode)) {
mDicNodePool.placeBackInstance(mDicNodesQueue.top());
mDicNodesQueue.pop();
mDicNodesQueue.push(pooledDicNode);
return;
}
mDicNodePool.placeBackInstance(pooledDicNode);
}
AK_FORCE_INLINE void copyPop(DicNode *dest) {
AK_FORCE_INLINE void copyPop(DicNode *const dest) {
if (mDicNodesQueue.empty()) {
ASSERT(false);
return;
......@@ -89,34 +88,16 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
if (dest) {
DicNodeUtils::initByCopy(node, dest);
}
node->finalize();
mDicNodePool.placeBackInstance(node);
mDicNodesQueue.pop();
}
void onReleased(const DicNode *dicNode) {
const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
if (mUnusedNodeIndices[index] != NOT_A_NODE_ID) {
// it's already released
return;
}
mUnusedNodeIndices[index] = mNextUnusedNodeId;
mNextUnusedNodeId = index;
ASSERT(index >= 0 && index < (mCapacity + 1));
}
AK_FORCE_INLINE void dump() const {
AKLOGI("\n\n\n\n\n===========================");
for (int i = 0; i < mCapacity + 1; ++i) {
if (mDicNodesBuf[i].isUsed()) {
mDicNodesBuf[i].dump("QUEUE: ");
}
}
AKLOGI("===========================\n\n\n\n\n");
AK_FORCE_INLINE void dump() {
mDicNodePool.dump();
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
static const int NOT_A_NODE_ID = -1;
AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left,
const DicNode *const right) {
......@@ -124,26 +105,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
}
struct DicNodeComparator {
bool operator ()(DicNode *left, DicNode *right) {
bool operator ()(const DicNode *left, const DicNode *right) const {
return compareDicNode(left, right);
}
};
typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
const int mCapacity;
int mMaxSize;
std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
std::vector<int> mUnusedNodeIndices;
int mNextUnusedNodeId;
DicNodesQueue mDicNodesQueue;
inline bool isFull(const int maxSize) const {
return getSize() >= maxSize;
}
AK_FORCE_INLINE void pop() {
copyPop(nullptr);
}
DicNodePool mDicNodePool;
AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const {
DicNode *worstNode = mDicNodesQueue.top();
......@@ -153,61 +123,13 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
return compareDicNode(dicNode, worstNode);
}
AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
if (mCapacity == 0) {
return nullptr;
}
if (mNextUnusedNodeId == NOT_A_NODE_ID) {
AKLOGI("No unused node found.");
for (int i = 0; i < mCapacity + 1; ++i) {
AKLOGI("Dump node availability, %d, %d, %d",
i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
}
ASSERT(false);
return nullptr;
}
DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId];
markNodeAsUsed(dicNode);
return dicNode;
}
AK_FORCE_INLINE void markNodeAsUsed(DicNode *dicNode) {
const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
mNextUnusedNodeId = mUnusedNodeIndices[index];
mUnusedNodeIndices[index] = NOT_A_NODE_ID;
ASSERT(index >= 0 && index < (mCapacity + 1));
}
AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
if (!dicNode) {
return nullptr;
}
if (!isFull(maxSize)) {
mDicNodesQueue.push(dicNode);
return dicNode;
}
if (betterThanWorstDicNode(dicNode)) {
pop();
mDicNodesQueue.push(dicNode);
return dicNode;
}
dicNode->finalize();
return nullptr;
}
// Copy
AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode, const int maxSize) {
return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
}
AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) {
DicNode *newNode = searchEmptyDicNode();
DicNode *newNode = mDicNodePool.getInstance();
if (newNode) {
DicNodeUtils::initByCopy(dicNode, newNode);
}
return newNode;
}
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
/*
* Copyright (C) 2012 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_DIC_NODE_RELEASE_LISTENER_H
#define LATINIME_DIC_NODE_RELEASE_LISTENER_H
#include "defines.h"
namespace latinime {
class DicNode;
class DicNodeReleaseListener {
public:
DicNodeReleaseListener() {}
virtual ~DicNodeReleaseListener() {}
virtual void onReleased(const DicNode *dicNode) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener);
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_RELEASE_LISTENER_H
......@@ -49,15 +49,14 @@ class DicNodesCache {
AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
mInputIndex = 0;
mLastCachedInputIndex = 0;
// We want to use the max capacity for the current active dic node queue.
mActiveDicNodes->clearAndResizeToCapacity();
// nextActiveSize is used to limit the next iteration's active dic node size.
// The size of current active DicNode queue doesn't have to be changed.
mActiveDicNodes->clear();
// nextActiveSize is used to limit the next iteration's active DicNode size.
const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity());
mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
mTerminalDicNodes->clearAndResize(terminalSize);
// We want to use the max capacity for the cached dic nodes that will be used for the
// continuous suggestion.
mCachedDicNodesForContinuousSuggestion->clearAndResizeToCapacity();
// The size of cached DicNode queue doesn't have to be changed.
mCachedDicNodesForContinuousSuggestion->clear();
}
AK_FORCE_INLINE void continueSearch() {
......@@ -95,8 +94,8 @@ class DicNodesCache {
mActiveDicNodes->copyPush(dicNode);
}
AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) {
return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
AK_FORCE_INLINE void copyPushContinue(DicNode *dicNode) {
mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
}
AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment