| 227 | |
| 228 | bool g_deleted = false; |
| 229 | void* ThreadKeyFunc(void* arg) { |
| 230 | auto thread_key_arg = (ThreadKeyArg*)arg; |
| 231 | auto thread_keys = thread_key_arg->thread_keys; |
| 232 | std::vector<int> expects(thread_keys.size(), 0); |
| 233 | for (auto key : thread_keys) { |
| 234 | EXPECT_TRUE(butil::thread_getspecific(*key) == NULL); |
| 235 | EXPECT_EQ(0, butil::thread_setspecific(*key, new int(0))); |
| 236 | EXPECT_EQ(*(static_cast<int*>(butil::thread_getspecific(*key))), 0); |
| 237 | } |
| 238 | while (!g_stopped) { |
| 239 | uint64_t index = |
| 240 | fast_rand_less_than(thread_keys.size()); |
| 241 | auto data = static_cast<int*>(butil::thread_getspecific(*thread_keys[index])); |
| 242 | EXPECT_TRUE(data != NULL); |
| 243 | EXPECT_EQ(*data, expects[index]); |
| 244 | ++(*data); |
| 245 | ++expects[index]; |
| 246 | bthread_usleep(10); |
| 247 | } |
| 248 | |
| 249 | thread_key_arg->ready_delete = true; |
| 250 | while (!g_deleted) { |
| 251 | bthread_usleep(10); |
| 252 | } |
| 253 | |
| 254 | for (auto key : thread_keys) { |
| 255 | EXPECT_TRUE(butil::thread_getspecific(*key) == NULL) |
| 256 | << butil::thread_getspecific(*key); |
| 257 | } |
| 258 | return NULL; |
| 259 | } |
| 260 | |
| 261 | TEST(ThreadLocalTest, thread_key_multi_thread) { |
| 262 | g_stopped = false; |
nothing calls this directly
no test coverage detected