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 #include "multi_thread_container_access.h"
17 
18 #include <cinttypes>
19 #include <cstdlib>
20 #include <list>
21 #include <map>
22 #include <memory>
23 #include <string>
24 #include <thread>
25 #include <vector>
26 
27 using namespace OHOS::HiviewDFX;
28 
29 static constexpr int MAP_INDEX_LEN = 10;
30 static constexpr int MAX_LOOP_SIZE = 10000;
31 static constexpr int THREAD_SIZE = 10;
32 
MultiThreadVectorAccess()33 int MultiThreadVectorAccess()
34 {
35     auto testcase = std::make_shared<MultiThreadContainerAccess>();
36     testcase->Print();
37     std::vector<std::thread> threads;
38     for (int i = 0; i < THREAD_SIZE; i++) {
39         std::thread th(
40             [testcase] {
41                 for (int i = 0; i < MAX_LOOP_SIZE; i++) {
42                     testcase->ManipulateVector();
43                 }
44                 testcase->Print();
45             });
46         threads.push_back(std::move(th));
47     }
48 
49     for (auto& th : threads) {
50         th.join();
51     }
52     return 0;
53 }
54 
MultiThreadMapAccess()55 int MultiThreadMapAccess()
56 {
57     auto testcase = std::make_shared<MultiThreadContainerAccess>();
58     testcase->Print();
59     std::vector<std::thread> threads;
60     for (int i = 0; i < THREAD_SIZE; i++) {
61         std::thread th(
62             [testcase] {
63                 for (int i = 0; i < MAX_LOOP_SIZE; i++) {
64                     testcase->ManipulateMap();
65                 }
66                 testcase->Print();
67             });
68         threads.push_back(std::move(th));
69     }
70 
71     for (auto& th : threads) {
72         th.join();
73     }
74     return 0;
75 }
76 
MultiThreadListAccess()77 int MultiThreadListAccess()
78 {
79     auto testcase = std::make_shared<MultiThreadContainerAccess>();
80     testcase->Print();
81     std::vector<std::thread> threads;
82     for (int i = 0; i < THREAD_SIZE; i++) {
83         std::thread th(
84             [testcase] {
85                 for (int i = 0; i < MAX_LOOP_SIZE; i++) {
86                     // may crash inside loop
87                     testcase->ManipulateList();
88                     testcase->Print();
89                 }
90             });
91         threads.push_back(std::move(th));
92     }
93 
94     for (auto& th : threads) {
95         th.join();
96     }
97     return 0;
98 }
99 namespace OHOS {
100 namespace HiviewDFX {
GenerateStr()101 std::string MultiThreadContainerAccess::GenerateStr()
102 {
103     constexpr int dictLen = 26;
104     constexpr int len = 10;
105     const char dict[dictLen] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
106         'h', 'i', 'j', 'k', 'l', 'm', 'n',
107         'o', 'p', 'q', 'r', 's', 't', 'u',
108         'v', 'w', 'x', 'y', 'z' };
109     std::string result = "";
110     for (int i = 0; i < len; i++) {
111         result = result + dict[rand() % dictLen];
112     }
113     return result;
114 }
115 
ManipulateVector()116 void MultiThreadContainerAccess::ManipulateVector()
117 {
118     if ((rand() % MANIPULATION_TYPE) == ADD) {
119         strVector_.push_back(GenerateStr());
120     } else if (!strVector_.empty()) {
121         strVector_.pop_back();
122     }
123 }
124 
ManipulateMap()125 void MultiThreadContainerAccess::ManipulateMap()
126 {
127     if ((rand() % MANIPULATION_TYPE) == ADD) {
128         strMap_[rand() % MAP_INDEX_LEN] = GenerateStr();
129     } else {
130         strMap_.erase(rand() % MAP_INDEX_LEN);
131     }
132 }
133 
ManipulateList()134 void MultiThreadContainerAccess::ManipulateList()
135 {
136     if ((rand() % MANIPULATION_TYPE) == ADD) {
137         strList_.push_back(GenerateStr());
138     } else if (!strList_.empty()) {
139         strList_.pop_back();
140     }
141 }
142 
Print() const143 void MultiThreadContainerAccess::Print() const
144 {
145     printf("MultiThreadContainerAccess::Print begin\n");
146     for (const auto& value : strList_) {
147         printf("List:%s\n", value.c_str());
148     }
149 
150     for (const auto& value : strVector_) {
151         printf("Vector:%s\n", value.c_str());
152     }
153 
154     for (const auto& entry : strMap_) {
155         printf("Map: key[%d]:value[%s]\n", entry.first, entry.second.c_str());
156     }
157     printf("MultiThreadContainerAccess::Print end\n");
158 }
159 } // namespace HiviewDFX
160 } // namespace OHOS
161