Home | History | Annotate | Download | only in dicnode
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef LATINIME_DIC_NODES_CACHE_H
     18 #define LATINIME_DIC_NODES_CACHE_H
     19 
     20 #include <algorithm>
     21 
     22 #include "defines.h"
     23 #include "suggest/core/dicnode/dic_node_priority_queue.h"
     24 
     25 namespace latinime {
     26 
     27 class DicNode;
     28 
     29 /**
     30  * Class for controlling dicNode search priority queue and lexicon trie traversal.
     31  */
     32 class DicNodesCache {
     33  public:
     34     AK_FORCE_INLINE explicit DicNodesCache(const bool usesLargeCapacityCache)
     35             : mUsesLargeCapacityCache(usesLargeCapacityCache),
     36               mDicNodePriorityQueue0(getCacheCapacity()),
     37               mDicNodePriorityQueue1(getCacheCapacity()),
     38               mDicNodePriorityQueue2(getCacheCapacity()),
     39               mDicNodePriorityQueueForTerminal(MAX_RESULTS),
     40               mActiveDicNodes(&mDicNodePriorityQueue0),
     41               mNextActiveDicNodes(&mDicNodePriorityQueue1),
     42               mCachedDicNodesForContinuousSuggestion(&mDicNodePriorityQueue2),
     43               mTerminalDicNodes(&mDicNodePriorityQueueForTerminal),
     44               mInputIndex(0), mLastCachedInputIndex(0) {}
     45 
     46     AK_FORCE_INLINE virtual ~DicNodesCache() {}
     47 
     48     AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
     49         mInputIndex = 0;
     50         mLastCachedInputIndex = 0;
     51         // The size of current active DicNode queue doesn't have to be changed.
     52         mActiveDicNodes->clear();
     53         // nextActiveSize is used to limit the next iteration's active DicNode size.
     54         const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity());
     55         mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
     56         mTerminalDicNodes->clearAndResize(terminalSize);
     57         // The size of cached DicNode queue doesn't have to be changed.
     58         mCachedDicNodesForContinuousSuggestion->clear();
     59     }
     60 
     61     AK_FORCE_INLINE void continueSearch() {
     62         resetTemporaryCaches();
     63         restoreActiveDicNodesFromCache();
     64     }
     65 
     66     AK_FORCE_INLINE void advanceActiveDicNodes() {
     67         if (DEBUG_DICT) {
     68             AKLOGI("Advance active %d nodes.", mNextActiveDicNodes->getSize());
     69         }
     70         if (DEBUG_DICT_FULL) {
     71             mNextActiveDicNodes->dump();
     72         }
     73         mNextActiveDicNodes =
     74                 moveNodesAndReturnReusableEmptyQueue(mNextActiveDicNodes, &mActiveDicNodes);
     75     }
     76 
     77     int activeSize() const { return mActiveDicNodes->getSize(); }
     78     int terminalSize() const { return mTerminalDicNodes->getSize(); }
     79     bool isLookAheadCorrectionInputIndex(const int inputIndex) const {
     80         return inputIndex == mInputIndex - 1;
     81     }
     82     void advanceInputIndex(const int inputSize) {
     83         if (mInputIndex < inputSize) {
     84             mInputIndex++;
     85         }
     86     }
     87 
     88     AK_FORCE_INLINE void copyPushTerminal(DicNode *dicNode) {
     89         mTerminalDicNodes->copyPush(dicNode);
     90     }
     91 
     92     AK_FORCE_INLINE void copyPushActive(DicNode *dicNode) {
     93         mActiveDicNodes->copyPush(dicNode);
     94     }
     95 
     96     AK_FORCE_INLINE void copyPushContinue(DicNode *dicNode) {
     97         mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
     98     }
     99 
    100     AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) {
    101         mNextActiveDicNodes->copyPush(dicNode);
    102     }
    103 
    104     void popTerminal(DicNode *dest) {
    105         mTerminalDicNodes->copyPop(dest);
    106     }
    107 
    108     void popActive(DicNode *dest) {
    109         mActiveDicNodes->copyPop(dest);
    110     }
    111 
    112     bool hasCachedDicNodesForContinuousSuggestion() const {
    113         return mCachedDicNodesForContinuousSuggestion
    114                 && mCachedDicNodesForContinuousSuggestion->getSize() > 0;
    115     }
    116 
    117     AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
    118         // TODO: Move this variable to header
    119         static const int CACHE_BACK_LENGTH = 3;
    120         const int cacheInputIndex = inputSize - CACHE_BACK_LENGTH;
    121         const bool shouldCache = (cacheInputIndex == mInputIndex)
    122                 && (cacheInputIndex != mLastCachedInputIndex);
    123         return shouldCache;
    124     }
    125 
    126     AK_FORCE_INLINE void updateLastCachedInputIndex() {
    127         mLastCachedInputIndex = mInputIndex;
    128     }
    129 
    130  private:
    131     DISALLOW_COPY_AND_ASSIGN(DicNodesCache);
    132 
    133     AK_FORCE_INLINE void restoreActiveDicNodesFromCache() {
    134         if (DEBUG_DICT) {
    135             AKLOGI("Restore %d nodes. inputIndex = %d.",
    136                     mCachedDicNodesForContinuousSuggestion->getSize(), mLastCachedInputIndex);
    137         }
    138         if (DEBUG_DICT_FULL || DEBUG_CACHE) {
    139             mCachedDicNodesForContinuousSuggestion->dump();
    140         }
    141         mInputIndex = mLastCachedInputIndex;
    142         mCachedDicNodesForContinuousSuggestion = moveNodesAndReturnReusableEmptyQueue(
    143                 mCachedDicNodesForContinuousSuggestion, &mActiveDicNodes);
    144     }
    145 
    146     AK_FORCE_INLINE static DicNodePriorityQueue *moveNodesAndReturnReusableEmptyQueue(
    147             DicNodePriorityQueue *src, DicNodePriorityQueue **dest) {
    148         const int srcMaxSize = src->getMaxSize();
    149         const int destMaxSize = (*dest)->getMaxSize();
    150         DicNodePriorityQueue *tmp = *dest;
    151         *dest = src;
    152         (*dest)->setMaxSize(destMaxSize);
    153         tmp->clearAndResize(srcMaxSize);
    154         return tmp;
    155     }
    156 
    157     AK_FORCE_INLINE int getCacheCapacity() const {
    158         return mUsesLargeCapacityCache ?
    159                 LARGE_PRIORITY_QUEUE_CAPACITY : SMALL_PRIORITY_QUEUE_CAPACITY;
    160     }
    161 
    162     AK_FORCE_INLINE void resetTemporaryCaches() {
    163         mActiveDicNodes->clear();
    164         mNextActiveDicNodes->clear();
    165         mTerminalDicNodes->clear();
    166     }
    167 
    168     static const int LARGE_PRIORITY_QUEUE_CAPACITY;
    169     static const int SMALL_PRIORITY_QUEUE_CAPACITY;
    170 
    171     const bool mUsesLargeCapacityCache;
    172     // Instances
    173     DicNodePriorityQueue mDicNodePriorityQueue0;
    174     DicNodePriorityQueue mDicNodePriorityQueue1;
    175     DicNodePriorityQueue mDicNodePriorityQueue2;
    176     DicNodePriorityQueue mDicNodePriorityQueueForTerminal;
    177 
    178     // Active dicNodes currently being expanded.
    179     DicNodePriorityQueue *mActiveDicNodes;
    180     // Next dicNodes to be expanded.
    181     DicNodePriorityQueue *mNextActiveDicNodes;
    182     // Cached dicNodes used for continuous suggestion.
    183     DicNodePriorityQueue *mCachedDicNodesForContinuousSuggestion;
    184     // Current top terminal dicNodes.
    185     DicNodePriorityQueue *mTerminalDicNodes;
    186     int mInputIndex;
    187     int mLastCachedInputIndex;
    188 };
    189 } // namespace latinime
    190 #endif // LATINIME_DIC_NODES_CACHE_H
    191