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>
20 namespace OHOS {
21 namespace NativePreferences {
22 
23 template<typename T>
24 class Pool {
25 public:
Pool(uint32_t capability,uint32_t min)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 
Idle(std::shared_ptr<T> data)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 
Clean(std::function<void (std::shared_ptr<T>)> close)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 
123 private:
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