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

Commit 67ff21f3 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi
Browse files

Separate DicNodePool from DicNodePriorityQueue.

Change-Id: Ie500a4185792c2ffa0f5185ea5919626fe31c6fe
parent 452cd2f6
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -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;
}

+1 −25
Original line number Diff line number Diff line
@@ -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;
+87 −0
Original line number Diff line number Diff line
/*
 * 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
+32 −110
Original line number Diff line number Diff line
@@ -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
+0 −35
Original line number Diff line number Diff line
/*
 * 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
Loading