1/*
2 * Copyright (C) 2014 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_NODE_POOL_H
18#define LATINIME_DIC_NODE_POOL_H
19
20#include <deque>
21#include <unordered_set>
22#include <vector>
23
24#include "defines.h"
25#include "suggest/core/dicnode/dic_node.h"
26
27namespace latinime {
28
29class DicNodePool {
30 public:
31    explicit DicNodePool(const int capacity) : mDicNodes(), mPooledDicNodes() {
32        reset(capacity);
33    }
34
35    void reset(const int capacity) {
36        if (capacity == static_cast<int>(mDicNodes.size())
37                && capacity == static_cast<int>(mPooledDicNodes.size())) {
38            // No need to reset.
39            return;
40        }
41        mDicNodes.resize(capacity);
42        mDicNodes.shrink_to_fit();
43        mPooledDicNodes.clear();
44        for (auto &dicNode : mDicNodes) {
45            mPooledDicNodes.emplace_back(&dicNode);
46        }
47    }
48
49    // Get a DicNode instance from the pool. The instance has to be returned by returnInstance().
50    DicNode *getInstance() {
51        if (mPooledDicNodes.empty()) {
52            return nullptr;
53        }
54        DicNode *const dicNode = mPooledDicNodes.back();
55        mPooledDicNodes.pop_back();
56        return dicNode;
57    }
58
59    // Return an instance that has been removed from the pool by getInstance() to the pool. The
60    // instance must not be used after returning without getInstance().
61    void placeBackInstance(DicNode *dicNode) {
62        mPooledDicNodes.emplace_back(dicNode);
63    }
64
65    void dump() const {
66        AKLOGI("\n\n\n\n\n===========================");
67        std::unordered_set<const DicNode*> usedDicNodes;
68        for (const auto &dicNode : mDicNodes) {
69            usedDicNodes.insert(&dicNode);
70        }
71        for (const auto &dicNodePtr : mPooledDicNodes) {
72            usedDicNodes.erase(dicNodePtr);
73        }
74        for (const auto &usedDicNodePtr : usedDicNodes) {
75            usedDicNodePtr->dump("DIC_NODE_POOL: ");
76        }
77        AKLOGI("===========================\n\n\n\n\n");
78    }
79
80 private:
81    DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePool);
82
83    std::vector<DicNode> mDicNodes;
84    std::deque<DicNode*> mPooledDicNodes;
85};
86} // namespace latinime
87#endif // LATINIME_DIC_NODE_POOL_H
88