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 #ifndef STRING_VIEW_UTIL_H
16 #define STRING_VIEW_UTIL_H
17 
18 #include <cstdio>
19 #include <string>
20 #include <securec.h>
21 #include <vector>
22 #include <pthread.h>
23 #include "cpp_define.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 #ifdef is_mac
28 class SpinLock {
29 public:
lock()30     void lock()
31     {
32         while (locked_.test_and_set(std::memory_order_acquire))
33             ;
34     }
unlock()35     void unlock()
36     {
37         locked_.clear(std::memory_order_release);
38     }
39 
40 private:
41     std::atomic_flag locked_ = ATOMIC_FLAG_INIT;
42 };
43 #endif
44 class StringViewHold {
45 public:
Get()46     static StringViewHold &Get()
47     {
48         static StringViewHold instance;
49         return instance;
50     }
51 
Hold(STRING_VIEW view)52     const char *Hold(STRING_VIEW view)
53     {
54 #ifndef is_mac
55         pthread_spin_lock(&spin_lock_);
56 #else
57         std::lock_guard<SpinLock> lockGurand(spinlock_);
58 #endif
59         if (view.size() == 0) {
60 #ifndef is_mac
61             pthread_spin_unlock(&spin_lock_);
62 #endif
63             return "";
64         }
65 
66         char *p = new (std::nothrow) char[view.size() + 1];
67         if (p == nullptr) {
68 #ifndef is_mac
69             pthread_spin_unlock(&spin_lock_);
70 #endif
71             return "";
72         }
73         if (memset_s(p, view.size() + 1, '\0', view.size() + 1) != 0) {
74 #ifndef is_mac
75             pthread_spin_unlock(&spin_lock_);
76 #endif
77             return "";
78         }
79         std::copy(view.data(), view.data() + view.size(), p);
80         views_.emplace_back(p);
81 #ifndef is_mac
82         pthread_spin_unlock(&spin_lock_);
83 #endif
84         return p;
85     }
86 
87     // only use in UT
Clean()88     void Clean()
89     {
90 #ifndef is_mac
91         pthread_spin_lock(&spin_lock_);
92 #else
93         std::lock_guard<SpinLock> lockGurand(spinlock_);
94 #endif
95         for (auto &p : views_) {
96             delete[] p;
97         }
98         views_.clear();
99 #ifndef is_mac
100         pthread_spin_unlock(&spin_lock_);
101 #endif
102     }
103 
104 private:
105 #ifndef is_mac
StringViewHold()106     StringViewHold()
107     {
108         pthread_spin_init(&spin_lock_, PTHREAD_PROCESS_PRIVATE);
109     }
110 #endif
~StringViewHold()111     ~StringViewHold()
112     {
113         Clean();
114 #ifndef is_mac
115         pthread_spin_destroy(&spin_lock_);
116 #endif
117     }
118 
119     std::vector<char *> views_;
120 #ifndef is_mac
121     pthread_spinlock_t spin_lock_;
122 #else
123     SpinLock spinlock_;
124 #endif
125 };
126 } // namespace HiviewDFX
127 } // namespace OHOS
128 #endif