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 PREFERENCES_FRAMEWORKS_POOL_H
17#define PREFERENCES_FRAMEWORKS_POOL_H
18#include <functional>
19#include <mutex>
20namespace OHOS {
21namespace NativePreferences {
22
23template<typename T>
24class Pool {
25public:
26    Pool(uint32_t capability, uint32_t min) : capability_(capability), min_(min) {}
27
28    std::shared_ptr<T> Get(bool isForce = false)
29    {
30        std::unique_lock<decltype(mutex_)> lock(mutex_);
31        if (idle_ == nullptr) {
32            if (!isForce && current_ >= capability_) {
33                return nullptr;
34            }
35            auto cur = new Node();
36            idle_ = cur;
37            current_++;
38        }
39        Node *cur = idle_;
40        idle_ = idle_->next;
41        if (idle_ != nullptr) {
42            idle_->prev = nullptr;
43        }
44        cur->next = busy_;
45        if (busy_ != nullptr) {
46            cur->prev = busy_->prev;
47            busy_->prev = cur;
48        }
49        busy_ = cur;
50        return cur->data;
51    };
52
53    int32_t Release(std::shared_ptr<T> data, bool force = false)
54    {
55        std::unique_lock<decltype(mutex_)> lock(mutex_);
56        Node *cur = idle_;
57        if (!force && current_ <= min_) {
58            return false;
59        }
60        while (cur != nullptr) {
61            if (cur->data == data) {
62                if (cur->next != nullptr) {
63                    cur->next->prev = cur->prev;
64                }
65                if (cur->prev != nullptr) {
66                    cur->prev->next = cur->next;
67                }
68                if (idle_ == cur) {
69                    idle_ = cur->next;
70                }
71                current_--;
72                delete cur;
73                return true;
74            } else {
75                cur = cur->next;
76                continue;
77            }
78        }
79        return false;
80    }
81
82    void Idle(std::shared_ptr<T> data)
83    {
84        std::unique_lock<decltype(mutex_)> lock(mutex_);
85        Node *cur = busy_;
86        while (cur != nullptr && cur->data != data) {
87            cur = cur->next;
88        }
89        if (cur == nullptr) {
90            return;
91        }
92        if (cur == busy_) {
93            busy_ = busy_->next;
94        }
95        if (cur->next != nullptr) {
96            cur->next->prev = cur->prev;
97        }
98        if (cur->prev != nullptr) {
99            cur->prev->next = cur->next;
100        }
101        cur->prev = nullptr;
102        cur->next = idle_;
103        if (idle_ != nullptr) {
104            idle_->prev = cur;
105        }
106        idle_ = cur;
107    }
108
109    int32_t Clean(std::function<void(std::shared_ptr<T>)> close) noexcept
110    {
111        auto temp = min_;
112        min_ = 0;
113        while (busy_ != nullptr) {
114            close(busy_->data);
115        }
116        while (idle_ != nullptr) {
117            close(idle_->data);
118        }
119        min_ = temp;
120        return true;
121    }
122
123private:
124    struct Node {
125        Node *prev = nullptr;
126        Node *next = nullptr;
127        std::shared_ptr<T> data = std::make_shared<T>();
128    };
129
130    uint32_t capability_;
131    uint32_t min_;
132    uint32_t current_ = 0;
133    Node *idle_ = nullptr;
134    Node *busy_ = nullptr;
135    std::mutex mutex_;
136};
137} // namespace NativePreferences
138} // namespace OHOS
139
140#endif // PREFERENCES_FRAMEWORKS_POOL_H
141