1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H
17#define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H
18#include <functional>
19#include <mutex>
20namespace OHOS {
21template<typename T>
22class Pool {
23public:
24    Pool(uint32_t capability, uint32_t min) : capability_(capability), min_(min) {}
25
26    std::shared_ptr<T> Get(bool isForce = false)
27    {
28        std::unique_lock<decltype(mutex_)> lock(mutex_);
29        if (idle_ == nullptr) {
30            if (!isForce && current_ >= capability_) {
31                return nullptr;
32            }
33            auto cur = new Node();
34            idle_ = cur;
35            current_++;
36        }
37        Node *cur = idle_;
38        idle_ = idle_->next;
39        if (idle_ != nullptr) {
40            idle_->prev = nullptr;
41        }
42        cur->next = busy_;
43        if (busy_ != nullptr) {
44            cur->prev = busy_->prev;
45            busy_->prev = cur;
46        }
47        busy_ = cur;
48        return cur->data;
49    };
50
51    int32_t Release(std::shared_ptr<T> data, bool force = false)
52    {
53        std::unique_lock<decltype(mutex_)> lock(mutex_);
54        Node *cur = idle_;
55        if (!force && current_ <= min_) {
56            return false;
57        }
58        while (cur != nullptr) {
59            if (cur->data == data) {
60                if (cur->next != nullptr) {
61                    cur->next->prev = cur->prev;
62                }
63                if (cur->prev != nullptr) {
64                    cur->prev->next = cur->next;
65                }
66                if (idle_ == cur) {
67                    idle_ = cur->next;
68                }
69                current_--;
70                delete cur;
71                return true;
72            } else {
73                cur = cur->next;
74                continue;
75            }
76        }
77        return false;
78    }
79
80    void Idle(std::shared_ptr<T> data)
81    {
82        std::unique_lock<decltype(mutex_)> lock(mutex_);
83        Node *cur = busy_;
84        while (cur != nullptr && cur->data != data) {
85            cur = cur->next;
86        }
87        if (cur == nullptr) {
88            return;
89        }
90        if (cur == busy_) {
91            busy_ = busy_->next;
92        }
93        if (cur->next != nullptr) {
94            cur->next->prev = cur->prev;
95        }
96        if (cur->prev != nullptr) {
97            cur->prev->next = cur->next;
98        }
99        cur->prev = nullptr;
100        cur->next = idle_;
101        if (idle_ != nullptr) {
102            idle_->prev = cur;
103        }
104        idle_ = cur;
105    }
106
107    int32_t Clean(std::function<void(std::shared_ptr<T>)> close) noexcept
108    {
109        auto temp = min_;
110        min_ = 0;
111        while (busy_ != nullptr) {
112            close(busy_->data);
113        }
114        while (idle_ != nullptr) {
115            close(idle_->data);
116        }
117        min_ = temp;
118        return true;
119    }
120
121private:
122    struct Node {
123        Node *prev = nullptr;
124        Node *next = nullptr;
125        std::shared_ptr<T> data = std::make_shared<T>();
126    };
127
128    uint32_t capability_;
129    uint32_t min_;
130    uint32_t current_ = 0;
131    Node *idle_ = nullptr;
132    Node *busy_ = nullptr;
133    std::mutex mutex_;
134};
135} // namespace OHOS
136
137#endif // OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H
138