| 206 | } |
| 207 | |
| 208 | void MultithreadedTestThread(TestHookList* list, int shift, |
| 209 | int thread_num) { |
| 210 | string message; |
| 211 | char buf[64]; |
| 212 | for (int i = 1; i < 1000; ++i) { |
| 213 | // In each loop, we insert a unique value, check it exists, remove it, and |
| 214 | // check it doesn't exist. We also record some stats to log at the end of |
| 215 | // each thread. Each insertion location and the length of the list is |
| 216 | // non-deterministic (except for the very first one, over all threads, and |
| 217 | // after the very last one the list should be empty). |
| 218 | int value = (i << shift) + thread_num; |
| 219 | EXPECT_TRUE(TestHookList_Add(list, value)); |
| 220 | sched_yield(); // Ensure some more interleaving. |
| 221 | uintptr_t values[kHookListMaxValues + 1]; |
| 222 | int num_values = TestHookList_Traverse(*list, values, kHookListMaxValues); |
| 223 | EXPECT_LT(0, num_values); |
| 224 | int value_index; |
| 225 | for (value_index = 0; |
| 226 | value_index < num_values && values[value_index] != value; |
| 227 | ++value_index) |
| 228 | ; |
| 229 | EXPECT_LT(value_index, num_values); // Should have found value. |
| 230 | snprintf(buf, sizeof(buf), "[%d/%d; ", value_index, num_values); |
| 231 | message += buf; |
| 232 | sched_yield(); |
| 233 | EXPECT_TRUE(TestHookList_Remove(list, value)); |
| 234 | sched_yield(); |
| 235 | num_values = TestHookList_Traverse(*list, values, kHookListMaxValues); |
| 236 | for (value_index = 0; |
| 237 | value_index < num_values && values[value_index] != value; |
| 238 | ++value_index) |
| 239 | ; |
| 240 | EXPECT_EQ(value_index, num_values); // Should not have found value. |
| 241 | snprintf(buf, sizeof(buf), "%d]", num_values); |
| 242 | message += buf; |
| 243 | sched_yield(); |
| 244 | } |
| 245 | fprintf(stderr, "thread %d: %s\n", thread_num, message.c_str()); |
| 246 | } |
| 247 | |
| 248 | static volatile int num_threads_remaining; |
| 249 | static TestHookList list = INIT_HOOK_LIST(69); |
no test coverage detected