This test checks read/writing between multiple threads simultaneously for a table of int and string keys.
It is normal for the string/string table to take longer than its int/int counterpart. The goal is to test for simlutaneous reading/writing only, not erasing. For erasing we would need to stop read/writing or pause before reloading. The table size is limited to 1000 only due to memory limits in docker containers for CI.
60{
61 clock_t int_begin = clock();
63 std::array<std::thread, MAX_THREADS> r;
64 std::array<std::thread, MAX_THREADS> w;
65
66#if SPLIT_THREADS
68#endif
69
70
72 table.insert(j, j);
73
74
76 r[i] = std::thread([&table, i] () {
77#if SPLIT_THREADS
80#else
81 int start = 0;
83#endif
85
86 clock_t t_begin = clock();
87
88 for (int j = start; j < end; j++) {
89 int val = table.at(j);
90 if (j != val) {
93 return;
94 }
95 }
96
98 printf("INT/INT Thread #%d - Read Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
99 });
100 }
101
102
104 w[i] = std::thread([&table, i] () {
105#if SPLIT_THREADS
108#else
109 int start = 0;
111#endif
113
114 clock_t t_begin = clock();
115
116 for (int j = start; j < end; j++)
117 table.insert(j, j);
118
120 printf("INT/INT Thread #%d - Write Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
121 });
122 }
123
125
127
129 BOOST_FAIL("Failed read.");
130
131 printf("INT/INT Read/Write Test Finished in %0.5fs\n", double(clock() - int_begin) / CLOCKS_PER_SEC);
132
133 int_begin = clock();
134
135
136 std::map<int, int> map = table.get_map();
137 int i = 0;
138 for (auto c : map) {
139 BOOST_CHECK_EQUAL(i, c.second);
140 i++;
141 }
142
143 printf("INT/INT Map Iteration Test Finished in %0.5fs\n", double(clock() - int_begin) / CLOCKS_PER_SEC);
144
145
147 BOOST_CHECK_EQUAL(j, table.at(j));
148
149 printf("INT/INT Finished in %0.5fs\n", double(clock() - int_begin) / CLOCKS_PER_SEC);
150
152 if (r[i].joinable()) r[i].join();
153 if (w[i].joinable()) w[i].join();
154 }
155
159
160
162 w[i] = std::thread([&table, i] () {
163#if SPLIT_THREADS
166#else
167 int start = 0;
169#endif
171
172 clock_t t_begin = clock();
173
174 for (int j = start; j < end; j++)
175 table.erase(j);
176
177 printf("INT/INT Thread #%d - Erase Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
178 });
179 }
180
182
183 while (table.size() > 0);
184
185 printf("INT/INT Collisions: %d\n", table.max_collisions());
186
188 if (w[i].joinable()) w[i].join();
189 }
190
194
195
196
197
198 clock_t str_begin = clock();
199 std::string chars("abcdefghijklmnopqrstuvwxyz"
200 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
201 "1234567890"
202 "!@#$%^&*()"
203 "`~-_=+[{]}\\|;:'\",<.>/? ");
205 std::vector<std::string> keylist, vallist;
206
207
211 key[i] = chars[rand() % (chars.size() - 1)];
212 val[i] = chars[rand() % (chars.size() - 1)];
213 }
214
215 keylist.push_back(key);
216 vallist.push_back(val);
217 str_table.insert(key, val);
218 }
219
220
222 r[i] = std::thread([&str_table, keylist, vallist, i] () {
223#if SPLIT_THREADS
226#else
227 int start = 0;
229#endif
231
232 clock_t t_begin = clock();
233
234 for (int j = start; j < end; j++) {
235 std::string val = str_table.at(keylist.at(j));
236 if (val.compare(vallist.at(j)) != 0) {
237
240 return;
241 }
242 }
243
245 printf("STR/STR Thread #%d - Read Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
246 });
247 }
248
249
251 w[i] = std::thread([&str_table, keylist, vallist, i] () {
252#if SPLIT_THREADS
255#else
256 int start = 0;
258#endif
260 clock_t t_begin = clock();
261
262 for (int j = start; j < end; j++)
263 str_table.insert(keylist.at(j), vallist.at(j));
264
266 printf("STR/STR Thread #%d - Write Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
267 });
268 }
269
271
273
275 BOOST_FAIL("Failed read.");
276
278 if (r[i].joinable()) r[i].join();
279 if (w[i].joinable()) w[i].join();
280 }
281
282 printf("STR/STR Read/Write Test Finished in %0.6fs\n", double(clock() - str_begin) / CLOCKS_PER_SEC);
283
284 str_begin = clock();
285
286
287 std::map<std::string, std::string> strmap = str_table.get_map();
288 i = 0;
289 for (auto str : keylist) {
290 BOOST_CHECK_EQUAL(strmap.at(str).compare(vallist.at(i)), 0);
291 i++;
292 }
293
294 printf("STR/STR Map Iteration Test Finished in %0.6fs\n", double(clock() - str_begin) / CLOCKS_PER_SEC);
295
296
297 i = 0;
298 for (auto str : keylist) {
299 BOOST_CHECK_EQUAL(vallist.at(i).compare(str_table.at(str)), 0);
300 i++;
301 }
302
304
305
307 w[i] = std::thread([&str_table, keylist, i] () {
308#if SPLIT_THREADS
311#else
312 int start = 0;
314#endif
316
317 clock_t t_begin = clock();
318
319 for (int j = start; j < end; j++)
320 str_table.erase(keylist.at(j));
321
322 printf("STR/STR Thread #%d - Erase Time %.5fs\n", i, double(clock() - t_begin) / CLOCKS_PER_SEC);
323 });
324 }
325
327
328 while (str_table.size() > 0);
329
330 printf("STR/STR Collisions: %d\n", str_table.max_collisions());
331
333 if (w[i].joinable()) w[i].join();
334 }
335}
#define MAX_TABLE_SIZE
Definition: LockedLookupTableTest.cpp:43
std::atomic< bool > done_write
Definition: LockedLookupTableTest.cpp:49
#define MAX_BUCKETS
Definition: LockedLookupTableTest.cpp:45
#define MAX_THREADS
Definition: LockedLookupTableTest.cpp:42
std::atomic< bool > fail
Definition: LockedLookupTableTest.cpp:49
std::atomic< bool > done_read
Definition: LockedLookupTableTest.cpp:49
std::atomic< bool > go
Definition: LockedLookupTableTest.cpp:49
#define STRING_SIZE
Definition: LockedLookupTableTest.cpp:44
Definition: LockedLookupTable.hpp:44