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

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
Loading
Loading
Loading
Loading
+1 −4
Original line number Original line Diff line number Diff line
@@ -24,8 +24,7 @@ DicNode::DicNode(const DicNode &dicNode)
          mProfiler(dicNode.mProfiler),
          mProfiler(dicNode.mProfiler),
#endif
#endif
          mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
          mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
          mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed),
          mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion) {
          mReleaseListener(nullptr) {
    /* empty */
    /* empty */
}
}


@@ -36,8 +35,6 @@ DicNode &DicNode::operator=(const DicNode &dicNode) {
    mDicNodeProperties = dicNode.mDicNodeProperties;
    mDicNodeProperties = dicNode.mDicNodeProperties;
    mDicNodeState = dicNode.mDicNodeState;
    mDicNodeState = dicNode.mDicNodeState;
    mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
    mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
    mIsUsed = dicNode.mIsUsed;
    mReleaseListener = dicNode.mReleaseListener;
    return *this;
    return *this;
}
}


+1 −25
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@


#include "defines.h"
#include "defines.h"
#include "suggest/core/dicnode/dic_node_profiler.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/dic_node_utils.h"
#include "suggest/core/dicnode/internal/dic_node_state.h"
#include "suggest/core/dicnode/internal/dic_node_state.h"
#include "suggest/core/dicnode/internal/dic_node_properties.h"
#include "suggest/core/dicnode/internal/dic_node_properties.h"
@@ -89,8 +88,7 @@ class DicNode {
#if DEBUG_DICT
#if DEBUG_DICT
              mProfiler(),
              mProfiler(),
#endif
#endif
              mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false),
              mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {}
              mIsUsed(false), mReleaseListener(nullptr) {}


    DicNode(const DicNode &dicNode);
    DicNode(const DicNode &dicNode);
    DicNode &operator=(const DicNode &dicNode);
    DicNode &operator=(const DicNode &dicNode);
@@ -98,7 +96,6 @@ class DicNode {


    // Init for copy
    // Init for copy
    void initByCopy(const DicNode *const dicNode) {
    void initByCopy(const DicNode *const dicNode) {
        mIsUsed = true;
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
        mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
        mDicNodeState.initByCopy(&dicNode->mDicNodeState);
        mDicNodeState.initByCopy(&dicNode->mDicNodeState);
@@ -107,7 +104,6 @@ class DicNode {


    // Init for root with prevWordPtNodePos which is used for bigram
    // Init for root with prevWordPtNodePos which is used for bigram
    void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
    void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
        mIsUsed = true;
        mIsCachedForNextSuggestion = false;
        mIsCachedForNextSuggestion = false;
        mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos);
        mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos);
        mDicNodeState.init();
        mDicNodeState.init();
@@ -116,7 +112,6 @@ class DicNode {


    // Init for root with previous word
    // Init for root with previous word
    void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
    void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
        mIsUsed = true;
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos());
        mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos());
        mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
        mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
@@ -125,7 +120,6 @@ class DicNode {
    }
    }


    void initAsPassingChild(DicNode *parentDicNode) {
    void initAsPassingChild(DicNode *parentDicNode) {
        mIsUsed = true;
        mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
        mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
        const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
        const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
        mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
        mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
@@ -137,7 +131,6 @@ class DicNode {
            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
            const bool hasChildren, const bool isBlacklistedOrNotAWord,
            const bool hasChildren, const bool isBlacklistedOrNotAWord,
            const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
            const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
        mIsUsed = true;
        uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
        uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
        const uint16_t newLeavingDepth = static_cast<uint16_t>(
        const uint16_t newLeavingDepth = static_cast<uint16_t>(
@@ -150,17 +143,6 @@ class DicNode {
        PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
        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 {
    bool isRoot() const {
        return getNodeCodePointCount() == 0;
        return getNodeCodePointCount() == 0;
    }
    }
@@ -466,10 +448,6 @@ class DicNode {
#endif
#endif
    }
    }


    void setReleaseListener(DicNodeReleaseListener *releaseListener) {
        mReleaseListener = releaseListener;
    }

    AK_FORCE_INLINE bool compare(const DicNode *right) const {
    AK_FORCE_INLINE bool compare(const DicNode *right) const {
        // Promote exact matches to prevent them from being pruned.
        // Promote exact matches to prevent them from being pruned.
        const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
        const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
@@ -507,8 +485,6 @@ class DicNode {
    DicNodeState mDicNodeState;
    DicNodeState mDicNodeState;
    // TODO: Remove
    // TODO: Remove
    bool mIsCachedForNextSuggestion;
    bool mIsCachedForNextSuggestion;
    bool mIsUsed;
    DicNodeReleaseListener *mReleaseListener;


    AK_FORCE_INLINE int getTotalInputIndex() const {
    AK_FORCE_INLINE int getTotalInputIndex() const {
        int index = 0;
        int index = 0;
+87 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -23,38 +23,30 @@


#include "defines.h"
#include "defines.h"
#include "suggest/core/dicnode/dic_node.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 {
namespace latinime {


class DicNodePriorityQueue : public DicNodeReleaseListener {
class DicNodePriorityQueue {
 public:
 public:
    AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
    AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
            : mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(),
            : mMaxSize(capacity), mDicNodesQueue(), mDicNodePool(capacity) {
              mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() {
        clear();
        mDicNodesBuf.resize(mCapacity + 1);
        mUnusedNodeIndices.resize(mCapacity + 1);
        clearAndResizeToCapacity();
    }
    }


    // Non virtual inline destructor -- never inherit this class
    // Non virtual inline destructor -- never inherit this class
    AK_FORCE_INLINE ~DicNodePriorityQueue() {}
    AK_FORCE_INLINE ~DicNodePriorityQueue() {}


    int getSize() const {
    AK_FORCE_INLINE int getSize() const {
        return static_cast<int>(mDicNodesQueue.size());
        return static_cast<int>(mDicNodesQueue.size());
    }
    }


    int getMaxSize() const {
    AK_FORCE_INLINE int getMaxSize() const {
        return mMaxSize;
        return mMaxSize;
    }
    }


    AK_FORCE_INLINE void setMaxSize(const int maxSize) {
    AK_FORCE_INLINE void setMaxSize(const int maxSize) {
        ASSERT(maxSize <= mCapacity);
        mMaxSize = maxSize;
        mMaxSize = std::min(maxSize, mCapacity);
    }

    AK_FORCE_INLINE void clearAndResizeToCapacity() {
        clearAndResize(mCapacity);
    }
    }


    AK_FORCE_INLINE void clear() {
    AK_FORCE_INLINE void clear() {
@@ -62,25 +54,32 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
    }
    }


    AK_FORCE_INLINE void clearAndResize(const int maxSize) {
    AK_FORCE_INLINE void clearAndResize(const int maxSize) {
        ASSERT(maxSize <= mCapacity);
        mMaxSize = maxSize;
        while (!mDicNodesQueue.empty()) {
        while (!mDicNodesQueue.empty()) {
            mDicNodesQueue.pop();
            mDicNodesQueue.pop();
        }
        }
        setMaxSize(maxSize);
        mDicNodePool.reset(mMaxSize + 1);
        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;
    }
    }


    // Copy
    AK_FORCE_INLINE void copyPush(const DicNode *const dicNode) {
    AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) {
        DicNode *const pooledDicNode = newDicNode(dicNode);
        return copyPush(dicNode, mMaxSize);
        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()) {
        if (mDicNodesQueue.empty()) {
            ASSERT(false);
            ASSERT(false);
            return;
            return;
@@ -89,34 +88,16 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
        if (dest) {
        if (dest) {
            DicNodeUtils::initByCopy(node, dest);
            DicNodeUtils::initByCopy(node, dest);
        }
        }
        node->finalize();
        mDicNodePool.placeBackInstance(node);
        mDicNodesQueue.pop();
        mDicNodesQueue.pop();
    }
    }


    void onReleased(const DicNode *dicNode) {
    AK_FORCE_INLINE void dump() {
        const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
        mDicNodePool.dump();
        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");
    }
    }


 private:
 private:
    DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
    DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
    static const int NOT_A_NODE_ID = -1;


    AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left,
    AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left,
            const DicNode *const right) {
            const DicNode *const right) {
@@ -124,26 +105,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
    }
    }


    struct DicNodeComparator {
    struct DicNodeComparator {
        bool operator ()(DicNode *left, DicNode *right) {
        bool operator ()(const DicNode *left, const DicNode *right) const {
            return compareDicNode(left, right);
            return compareDicNode(left, right);
        }
        }
    };
    };


    typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
    typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
    const int mCapacity;
    int mMaxSize;
    int mMaxSize;
    std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
    std::vector<int> mUnusedNodeIndices;
    int mNextUnusedNodeId;
    DicNodesQueue mDicNodesQueue;
    DicNodesQueue mDicNodesQueue;

    DicNodePool mDicNodePool;
    inline bool isFull(const int maxSize) const {
        return getSize() >= maxSize;
    }

    AK_FORCE_INLINE void pop() {
        copyPop(nullptr);
    }


    AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const {
    AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const {
        DicNode *worstNode = mDicNodesQueue.top();
        DicNode *worstNode = mDicNodesQueue.top();
@@ -153,61 +123,13 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
        return compareDicNode(dicNode, worstNode);
        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) {
    AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) {
        DicNode *newNode = searchEmptyDicNode();
        DicNode *newNode = mDicNodePool.getInstance();
        if (newNode) {
        if (newNode) {
            DicNodeUtils::initByCopy(dicNode, newNode);
            DicNodeUtils::initByCopy(dicNode, newNode);
        }
        }
        return newNode;
        return newNode;
    }
    }

};
};
} // namespace latinime
} // namespace latinime
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
+0 −35
Original line number Original line 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