aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.cpp5
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h26
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_pool.h87
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h142
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_release_listener.h35
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_nodes_cache.h15
6 files changed, 128 insertions, 182 deletions
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp
index 73855977e..414dc3b1e 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp
@@ -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;
}
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 258aa9ce3..b54c39f75 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -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;
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_pool.h b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
new file mode 100644
index 000000000..a660b744f
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
@@ -0,0 +1,87 @@
+/*
+ * 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
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
index 213b1b968..7b753f2e4 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.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
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
deleted file mode 100644
index c3f432951..000000000
--- a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
index 6b8dc8c96..089d4467f 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.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) {