thread_local_unittest.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/threading/thread_local.h"
  5. #include "base/check_op.h"
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/synchronization/waitable_event.h"
  8. #include "base/test/bind.h"
  9. #include "base/test/gtest_util.h"
  10. #include "base/threading/simple_thread.h"
  11. #include "base/threading/thread.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. #include "third_party/abseil-cpp/absl/types/optional.h"
  14. namespace base {
  15. namespace {
  16. class ThreadLocalTesterBase : public DelegateSimpleThreadPool::Delegate {
  17. public:
  18. typedef ThreadLocalPointer<char> TLPType;
  19. ThreadLocalTesterBase(TLPType* tlp, WaitableEvent* done)
  20. : tlp_(tlp), done_(done) {}
  21. ~ThreadLocalTesterBase() override = default;
  22. protected:
  23. raw_ptr<TLPType> tlp_;
  24. raw_ptr<WaitableEvent> done_;
  25. };
  26. class SetThreadLocal : public ThreadLocalTesterBase {
  27. public:
  28. SetThreadLocal(TLPType* tlp, WaitableEvent* done)
  29. : ThreadLocalTesterBase(tlp, done), val_(nullptr) {}
  30. ~SetThreadLocal() override = default;
  31. void set_value(char* val) { val_ = val; }
  32. void Run() override {
  33. DCHECK(!done_->IsSignaled());
  34. tlp_->Set(val_.get());
  35. done_->Signal();
  36. }
  37. private:
  38. raw_ptr<char> val_;
  39. };
  40. class GetThreadLocal : public ThreadLocalTesterBase {
  41. public:
  42. GetThreadLocal(TLPType* tlp, WaitableEvent* done)
  43. : ThreadLocalTesterBase(tlp, done), ptr_(nullptr) {}
  44. ~GetThreadLocal() override = default;
  45. void set_ptr(char** ptr) { ptr_ = ptr; }
  46. void Run() override {
  47. DCHECK(!done_->IsSignaled());
  48. *ptr_ = tlp_->Get();
  49. done_->Signal();
  50. }
  51. private:
  52. raw_ptr<char*> ptr_;
  53. };
  54. } // namespace
  55. // In this test, we start 2 threads which will access a ThreadLocalPointer. We
  56. // make sure the default is NULL, and the pointers are unique to the threads.
  57. TEST(ThreadLocalTest, Pointer) {
  58. DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
  59. DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
  60. tp1.Start();
  61. tp2.Start();
  62. ThreadLocalPointer<char> tlp;
  63. static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
  64. char* tls_val;
  65. WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
  66. WaitableEvent::InitialState::NOT_SIGNALED);
  67. GetThreadLocal getter(&tlp, &done);
  68. getter.set_ptr(&tls_val);
  69. // Check that both threads defaulted to NULL.
  70. tls_val = kBogusPointer;
  71. done.Reset();
  72. tp1.AddWork(&getter);
  73. done.Wait();
  74. EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
  75. tls_val = kBogusPointer;
  76. done.Reset();
  77. tp2.AddWork(&getter);
  78. done.Wait();
  79. EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
  80. SetThreadLocal setter(&tlp, &done);
  81. setter.set_value(kBogusPointer);
  82. // Have thread 1 set their pointer value to kBogusPointer.
  83. done.Reset();
  84. tp1.AddWork(&setter);
  85. done.Wait();
  86. tls_val = nullptr;
  87. done.Reset();
  88. tp1.AddWork(&getter);
  89. done.Wait();
  90. EXPECT_EQ(kBogusPointer, tls_val);
  91. // Make sure thread 2 is still NULL
  92. tls_val = kBogusPointer;
  93. done.Reset();
  94. tp2.AddWork(&getter);
  95. done.Wait();
  96. EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
  97. // Set thread 2 to kBogusPointer + 1.
  98. setter.set_value(kBogusPointer + 1);
  99. done.Reset();
  100. tp2.AddWork(&setter);
  101. done.Wait();
  102. tls_val = nullptr;
  103. done.Reset();
  104. tp2.AddWork(&getter);
  105. done.Wait();
  106. EXPECT_EQ(kBogusPointer + 1, tls_val);
  107. // Make sure thread 1 is still kBogusPointer.
  108. tls_val = nullptr;
  109. done.Reset();
  110. tp1.AddWork(&getter);
  111. done.Wait();
  112. EXPECT_EQ(kBogusPointer, tls_val);
  113. tp1.JoinAll();
  114. tp2.JoinAll();
  115. }
  116. namespace {
  117. // A simple helper which sets the given boolean to true on destruction.
  118. class SetTrueOnDestruction {
  119. public:
  120. SetTrueOnDestruction(bool* was_destroyed) : was_destroyed_(was_destroyed) {
  121. CHECK(was_destroyed != nullptr);
  122. }
  123. SetTrueOnDestruction(const SetTrueOnDestruction&) = delete;
  124. SetTrueOnDestruction& operator=(const SetTrueOnDestruction&) = delete;
  125. ~SetTrueOnDestruction() {
  126. EXPECT_FALSE(*was_destroyed_);
  127. *was_destroyed_ = true;
  128. }
  129. private:
  130. const raw_ptr<bool> was_destroyed_;
  131. };
  132. } // namespace
  133. TEST(ThreadLocalTest, ThreadLocalOwnedPointerBasic) {
  134. ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
  135. EXPECT_FALSE(tls_owned_pointer.Get());
  136. bool was_destroyed1 = false;
  137. tls_owned_pointer.Set(
  138. std::make_unique<SetTrueOnDestruction>(&was_destroyed1));
  139. EXPECT_FALSE(was_destroyed1);
  140. EXPECT_TRUE(tls_owned_pointer.Get());
  141. bool was_destroyed2 = false;
  142. tls_owned_pointer.Set(
  143. std::make_unique<SetTrueOnDestruction>(&was_destroyed2));
  144. EXPECT_TRUE(was_destroyed1);
  145. EXPECT_FALSE(was_destroyed2);
  146. EXPECT_TRUE(tls_owned_pointer.Get());
  147. tls_owned_pointer.Set(nullptr);
  148. EXPECT_TRUE(was_destroyed1);
  149. EXPECT_TRUE(was_destroyed2);
  150. EXPECT_FALSE(tls_owned_pointer.Get());
  151. }
  152. TEST(ThreadLocalTest, ThreadLocalOwnedPointerFreedOnThreadExit) {
  153. bool tls_was_destroyed = false;
  154. ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
  155. Thread thread("TestThread");
  156. thread.Start();
  157. WaitableEvent tls_set;
  158. thread.task_runner()->PostTask(
  159. FROM_HERE, BindLambdaForTesting([&]() {
  160. tls_owned_pointer.Set(
  161. std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed));
  162. tls_set.Signal();
  163. }));
  164. tls_set.Wait();
  165. EXPECT_FALSE(tls_was_destroyed);
  166. thread.Stop();
  167. EXPECT_TRUE(tls_was_destroyed);
  168. }
  169. TEST(ThreadLocalTest, ThreadLocalOwnedPointerCleansUpMainThreadOnDestruction) {
  170. absl::optional<ThreadLocalOwnedPointer<SetTrueOnDestruction>>
  171. tls_owned_pointer(absl::in_place);
  172. bool tls_was_destroyed_other = false;
  173. Thread thread("TestThread");
  174. thread.Start();
  175. WaitableEvent tls_set;
  176. thread.task_runner()->PostTask(
  177. FROM_HERE, BindLambdaForTesting([&]() {
  178. tls_owned_pointer->Set(
  179. std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed_other));
  180. tls_set.Signal();
  181. }));
  182. tls_set.Wait();
  183. bool tls_was_destroyed_main = false;
  184. tls_owned_pointer->Set(
  185. std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed_main));
  186. EXPECT_FALSE(tls_was_destroyed_other);
  187. EXPECT_FALSE(tls_was_destroyed_main);
  188. // Stopping the thread relinquishes its TLS (as in
  189. // ThreadLocalOwnedPointerFreedOnThreadExit).
  190. thread.Stop();
  191. EXPECT_TRUE(tls_was_destroyed_other);
  192. EXPECT_FALSE(tls_was_destroyed_main);
  193. // Deleting the ThreadLocalOwnedPointer instance on the main thread is allowed
  194. // iff that's the only thread with remaining storage (ref. disallowed use case
  195. // in ThreadLocalOwnedPointerDeathIfDestroyedWithActiveThread below). In that
  196. // case, the storage on the main thread is freed before releasing the TLS
  197. // slot.
  198. tls_owned_pointer.reset();
  199. EXPECT_TRUE(tls_was_destroyed_main);
  200. }
  201. TEST(ThreadLocalTest, ThreadLocalOwnedPointerDeathIfDestroyedWithActiveThread) {
  202. testing::FLAGS_gtest_death_test_style = "threadsafe";
  203. absl::optional<ThreadLocalOwnedPointer<int>> tls_owned_pointer(
  204. absl::in_place);
  205. Thread thread("TestThread");
  206. thread.Start();
  207. WaitableEvent tls_set;
  208. thread.task_runner()->PostTask(
  209. FROM_HERE, BindLambdaForTesting([&]() {
  210. tls_owned_pointer->Set(std::make_unique<int>(1));
  211. tls_set.Signal();
  212. }));
  213. tls_set.Wait();
  214. EXPECT_DCHECK_DEATH({ tls_owned_pointer.reset(); });
  215. }
  216. TEST(ThreadLocalTest, ThreadLocalOwnedPointerMultiThreadedAndStaticStorage) {
  217. constexpr int kNumThreads = 16;
  218. static ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
  219. std::array<bool, kNumThreads> were_destroyed{};
  220. std::array<std::unique_ptr<Thread>, kNumThreads> threads;
  221. for (auto& thread : threads) {
  222. thread = std::make_unique<Thread>("TestThread");
  223. thread->Start();
  224. }
  225. for (const auto& thread : threads) {
  226. // Waiting is unnecessary but enhances the likelihood of data races in the
  227. // next steps.
  228. thread->WaitUntilThreadStarted();
  229. }
  230. for (const bool was_destroyed : were_destroyed) {
  231. EXPECT_FALSE(was_destroyed);
  232. }
  233. for (int i = 0; i < kNumThreads; ++i) {
  234. threads[i]->task_runner()->PostTask(
  235. FROM_HERE,
  236. BindOnce(
  237. [](bool* was_destroyed) {
  238. tls_owned_pointer.Set(
  239. std::make_unique<SetTrueOnDestruction>(was_destroyed));
  240. },
  241. &were_destroyed[i]));
  242. }
  243. static bool main_thread_was_destroyed = false;
  244. // Even when the test is run multiple times in the same process: TLS should
  245. // never be destroyed until static uninitialization.
  246. EXPECT_FALSE(main_thread_was_destroyed);
  247. tls_owned_pointer.Set(
  248. std::make_unique<SetTrueOnDestruction>(&main_thread_was_destroyed));
  249. for (const auto& thread : threads) {
  250. thread->Stop();
  251. }
  252. for (const bool was_destroyed : were_destroyed) {
  253. EXPECT_TRUE(was_destroyed);
  254. }
  255. // The main thread's TLS still wasn't destroyed (let the test unfold naturally
  256. // through static uninitialization).
  257. EXPECT_FALSE(main_thread_was_destroyed);
  258. }
  259. TEST(ThreadLocalTest, Boolean) {
  260. {
  261. ThreadLocalBoolean tlb;
  262. EXPECT_FALSE(tlb.Get());
  263. tlb.Set(false);
  264. EXPECT_FALSE(tlb.Get());
  265. tlb.Set(true);
  266. EXPECT_TRUE(tlb.Get());
  267. }
  268. // Our slot should have been freed, we're all reset.
  269. {
  270. ThreadLocalBoolean tlb;
  271. EXPECT_FALSE(tlb.Get());
  272. }
  273. }
  274. } // namespace base