baidu_thread_local_unittest.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. #include <gtest/gtest.h>
  18. #include <errno.h>
  19. #include "butil/thread_local.h"
  20. namespace {
  21. BAIDU_THREAD_LOCAL int * dummy = NULL;
  22. const size_t NTHREAD = 8;
  23. static bool processed[NTHREAD+1];
  24. static bool deleted[NTHREAD+1];
  25. static bool register_check = false;
  26. struct YellObj {
  27. static int nc;
  28. static int nd;
  29. YellObj() {
  30. ++nc;
  31. }
  32. ~YellObj() {
  33. ++nd;
  34. }
  35. };
  36. int YellObj::nc = 0;
  37. int YellObj::nd = 0;
  38. static void check_global_variable() {
  39. EXPECT_TRUE(processed[NTHREAD]);
  40. EXPECT_TRUE(deleted[NTHREAD]);
  41. EXPECT_EQ(2, YellObj::nc);
  42. EXPECT_EQ(2, YellObj::nd);
  43. }
  44. class BaiduThreadLocalTest : public ::testing::Test{
  45. protected:
  46. BaiduThreadLocalTest(){
  47. if (!register_check) {
  48. register_check = true;
  49. butil::thread_atexit(check_global_variable);
  50. }
  51. };
  52. virtual ~BaiduThreadLocalTest(){};
  53. virtual void SetUp() {
  54. };
  55. virtual void TearDown() {
  56. };
  57. };
  58. BAIDU_THREAD_LOCAL void* x;
  59. void* foo(void* arg) {
  60. x = arg;
  61. usleep(10000);
  62. printf("x=%p\n", x);
  63. return NULL;
  64. }
  65. TEST_F(BaiduThreadLocalTest, thread_local_keyword) {
  66. pthread_t th[2];
  67. pthread_create(&th[0], NULL, foo, (void*)1);
  68. pthread_create(&th[1], NULL, foo, (void*)2);
  69. pthread_join(th[0], NULL);
  70. pthread_join(th[1], NULL);
  71. }
  72. void* yell(void*) {
  73. YellObj* p = butil::get_thread_local<YellObj>();
  74. EXPECT_TRUE(p);
  75. EXPECT_EQ(2, YellObj::nc);
  76. EXPECT_EQ(0, YellObj::nd);
  77. EXPECT_EQ(p, butil::get_thread_local<YellObj>());
  78. EXPECT_EQ(2, YellObj::nc);
  79. EXPECT_EQ(0, YellObj::nd);
  80. return NULL;
  81. }
  82. TEST_F(BaiduThreadLocalTest, get_thread_local) {
  83. YellObj::nc = 0;
  84. YellObj::nd = 0;
  85. YellObj* p = butil::get_thread_local<YellObj>();
  86. ASSERT_TRUE(p);
  87. ASSERT_EQ(1, YellObj::nc);
  88. ASSERT_EQ(0, YellObj::nd);
  89. ASSERT_EQ(p, butil::get_thread_local<YellObj>());
  90. ASSERT_EQ(1, YellObj::nc);
  91. ASSERT_EQ(0, YellObj::nd);
  92. pthread_t th;
  93. ASSERT_EQ(0, pthread_create(&th, NULL, yell, NULL));
  94. pthread_join(th, NULL);
  95. EXPECT_EQ(2, YellObj::nc);
  96. EXPECT_EQ(1, YellObj::nd);
  97. }
  98. void delete_dummy(void* arg) {
  99. *(bool*)arg = true;
  100. if (dummy) {
  101. delete dummy;
  102. dummy = NULL;
  103. } else {
  104. printf("dummy is NULL\n");
  105. }
  106. }
  107. void* proc_dummy(void* arg) {
  108. bool *p = (bool*)arg;
  109. *p = true;
  110. EXPECT_TRUE(dummy == NULL);
  111. dummy = new int(p - processed);
  112. butil::thread_atexit(delete_dummy, deleted + (p - processed));
  113. return NULL;
  114. }
  115. TEST_F(BaiduThreadLocalTest, sanity) {
  116. errno = 0;
  117. ASSERT_EQ(-1, butil::thread_atexit(NULL));
  118. ASSERT_EQ(EINVAL, errno);
  119. processed[NTHREAD] = false;
  120. deleted[NTHREAD] = false;
  121. proc_dummy(&processed[NTHREAD]);
  122. pthread_t th[NTHREAD];
  123. for (size_t i = 0; i < NTHREAD; ++i) {
  124. processed[i] = false;
  125. deleted[i] = false;
  126. ASSERT_EQ(0, pthread_create(&th[i], NULL, proc_dummy, processed + i));
  127. }
  128. for (size_t i = 0; i < NTHREAD; ++i) {
  129. ASSERT_EQ(0, pthread_join(th[i], NULL));
  130. ASSERT_TRUE(processed[i]);
  131. ASSERT_TRUE(deleted[i]);
  132. }
  133. }
  134. static std::ostringstream* oss = NULL;
  135. inline std::ostringstream& get_oss() {
  136. if (oss == NULL) {
  137. oss = new std::ostringstream;
  138. }
  139. return *oss;
  140. }
  141. void fun1() {
  142. get_oss() << "fun1" << std::endl;
  143. }
  144. void fun2() {
  145. get_oss() << "fun2" << std::endl;
  146. }
  147. void fun3(void* arg) {
  148. get_oss() << "fun3(" << (uintptr_t)arg << ")" << std::endl;
  149. }
  150. void fun4(void* arg) {
  151. get_oss() << "fun4(" << (uintptr_t)arg << ")" << std::endl;
  152. }
  153. static void check_result() {
  154. // Don't use gtest function since this function might be invoked when the main
  155. // thread quits, instances required by gtest functions are likely destroyed.
  156. assert(get_oss().str() == "fun4(0)\nfun3(2)\nfun2\n");
  157. }
  158. TEST_F(BaiduThreadLocalTest, call_order_and_cancel) {
  159. butil::thread_atexit_cancel(NULL);
  160. butil::thread_atexit_cancel(NULL, NULL);
  161. ASSERT_EQ(0, butil::thread_atexit(check_result));
  162. ASSERT_EQ(0, butil::thread_atexit(fun1));
  163. ASSERT_EQ(0, butil::thread_atexit(fun1));
  164. ASSERT_EQ(0, butil::thread_atexit(fun2));
  165. ASSERT_EQ(0, butil::thread_atexit(fun3, (void*)1));
  166. ASSERT_EQ(0, butil::thread_atexit(fun3, (void*)1));
  167. ASSERT_EQ(0, butil::thread_atexit(fun3, (void*)2));
  168. ASSERT_EQ(0, butil::thread_atexit(fun4, NULL));
  169. butil::thread_atexit_cancel(NULL);
  170. butil::thread_atexit_cancel(NULL, NULL);
  171. butil::thread_atexit_cancel(fun1);
  172. butil::thread_atexit_cancel(fun3, NULL);
  173. butil::thread_atexit_cancel(fun3, (void*)1);
  174. }
  175. } // namespace