xref: /aosp_15_r20/external/cronet/base/threading/thread_local_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_local.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <optional>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/test/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread.h"
16*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // A simple helper which sets the given boolean to true on destruction.
23*6777b538SAndroid Build Coastguard Worker class SetTrueOnDestruction {
24*6777b538SAndroid Build Coastguard Worker  public:
SetTrueOnDestruction(bool * was_destroyed)25*6777b538SAndroid Build Coastguard Worker   explicit SetTrueOnDestruction(bool* was_destroyed)
26*6777b538SAndroid Build Coastguard Worker       : was_destroyed_(was_destroyed) {
27*6777b538SAndroid Build Coastguard Worker     CHECK_NE(was_destroyed, nullptr);
28*6777b538SAndroid Build Coastguard Worker   }
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker   SetTrueOnDestruction(const SetTrueOnDestruction&) = delete;
31*6777b538SAndroid Build Coastguard Worker   SetTrueOnDestruction& operator=(const SetTrueOnDestruction&) = delete;
32*6777b538SAndroid Build Coastguard Worker 
~SetTrueOnDestruction()33*6777b538SAndroid Build Coastguard Worker   ~SetTrueOnDestruction() {
34*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(*was_destroyed_);
35*6777b538SAndroid Build Coastguard Worker     *was_destroyed_ = true;
36*6777b538SAndroid Build Coastguard Worker   }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker  private:
39*6777b538SAndroid Build Coastguard Worker   const raw_ptr<bool> was_destroyed_;
40*6777b538SAndroid Build Coastguard Worker };
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker }  // namespace
43*6777b538SAndroid Build Coastguard Worker 
TEST(ThreadLocalTest,ThreadLocalOwnedPointerBasic)44*6777b538SAndroid Build Coastguard Worker TEST(ThreadLocalTest, ThreadLocalOwnedPointerBasic) {
45*6777b538SAndroid Build Coastguard Worker   ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
46*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_owned_pointer.Get());
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   bool was_destroyed1 = false;
49*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer.Set(
50*6777b538SAndroid Build Coastguard Worker       std::make_unique<SetTrueOnDestruction>(&was_destroyed1));
51*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(was_destroyed1);
52*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(tls_owned_pointer.Get());
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   bool was_destroyed2 = false;
55*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer.Set(
56*6777b538SAndroid Build Coastguard Worker       std::make_unique<SetTrueOnDestruction>(&was_destroyed2));
57*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(was_destroyed1);
58*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(was_destroyed2);
59*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(tls_owned_pointer.Get());
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer.Set(nullptr);
62*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(was_destroyed1);
63*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(was_destroyed2);
64*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_owned_pointer.Get());
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker 
TEST(ThreadLocalTest,ThreadLocalOwnedPointerFreedOnThreadExit)67*6777b538SAndroid Build Coastguard Worker TEST(ThreadLocalTest, ThreadLocalOwnedPointerFreedOnThreadExit) {
68*6777b538SAndroid Build Coastguard Worker   bool tls_was_destroyed = false;
69*6777b538SAndroid Build Coastguard Worker   ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker   Thread thread("TestThread");
72*6777b538SAndroid Build Coastguard Worker   thread.Start();
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   WaitableEvent tls_set;
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   thread.task_runner()->PostTask(
77*6777b538SAndroid Build Coastguard Worker       FROM_HERE, BindLambdaForTesting([&]() {
78*6777b538SAndroid Build Coastguard Worker         tls_owned_pointer.Set(
79*6777b538SAndroid Build Coastguard Worker             std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed));
80*6777b538SAndroid Build Coastguard Worker         tls_set.Signal();
81*6777b538SAndroid Build Coastguard Worker       }));
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker   tls_set.Wait();
84*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_was_destroyed);
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   thread.Stop();
87*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(tls_was_destroyed);
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
TEST(ThreadLocalTest,ThreadLocalOwnedPointerCleansUpMainThreadOnDestruction)90*6777b538SAndroid Build Coastguard Worker TEST(ThreadLocalTest, ThreadLocalOwnedPointerCleansUpMainThreadOnDestruction) {
91*6777b538SAndroid Build Coastguard Worker   std::optional<ThreadLocalOwnedPointer<SetTrueOnDestruction>>
92*6777b538SAndroid Build Coastguard Worker       tls_owned_pointer(std::in_place);
93*6777b538SAndroid Build Coastguard Worker   bool tls_was_destroyed_other = false;
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   Thread thread("TestThread");
96*6777b538SAndroid Build Coastguard Worker   thread.Start();
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   WaitableEvent tls_set;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   thread.task_runner()->PostTask(
101*6777b538SAndroid Build Coastguard Worker       FROM_HERE, BindLambdaForTesting([&]() {
102*6777b538SAndroid Build Coastguard Worker         tls_owned_pointer->Set(
103*6777b538SAndroid Build Coastguard Worker             std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed_other));
104*6777b538SAndroid Build Coastguard Worker         tls_set.Signal();
105*6777b538SAndroid Build Coastguard Worker       }));
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   tls_set.Wait();
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   bool tls_was_destroyed_main = false;
110*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer->Set(
111*6777b538SAndroid Build Coastguard Worker       std::make_unique<SetTrueOnDestruction>(&tls_was_destroyed_main));
112*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_was_destroyed_other);
113*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_was_destroyed_main);
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   // Stopping the thread relinquishes its TLS (as in
116*6777b538SAndroid Build Coastguard Worker   // ThreadLocalOwnedPointerFreedOnThreadExit).
117*6777b538SAndroid Build Coastguard Worker   thread.Stop();
118*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(tls_was_destroyed_other);
119*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(tls_was_destroyed_main);
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   // Deleting the ThreadLocalOwnedPointer instance on the main thread is allowed
122*6777b538SAndroid Build Coastguard Worker   // iff that's the only thread with remaining storage (ref. disallowed use case
123*6777b538SAndroid Build Coastguard Worker   // in ThreadLocalOwnedPointerDeathIfDestroyedWithActiveThread below). In that
124*6777b538SAndroid Build Coastguard Worker   // case, the storage on the main thread is freed before releasing the TLS
125*6777b538SAndroid Build Coastguard Worker   // slot.
126*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer.reset();
127*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(tls_was_destroyed_main);
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
TEST(ThreadLocalTest,ThreadLocalOwnedPointerDeathIfDestroyedWithActiveThread)130*6777b538SAndroid Build Coastguard Worker TEST(ThreadLocalTest, ThreadLocalOwnedPointerDeathIfDestroyedWithActiveThread) {
131*6777b538SAndroid Build Coastguard Worker   GTEST_FLAG_SET(death_test_style, "threadsafe");
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker   std::optional<ThreadLocalOwnedPointer<int>> tls_owned_pointer(std::in_place);
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   Thread thread("TestThread");
136*6777b538SAndroid Build Coastguard Worker   thread.Start();
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker   WaitableEvent tls_set;
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   thread.task_runner()->PostTask(
141*6777b538SAndroid Build Coastguard Worker       FROM_HERE, BindLambdaForTesting([&]() {
142*6777b538SAndroid Build Coastguard Worker         tls_owned_pointer->Set(std::make_unique<int>(1));
143*6777b538SAndroid Build Coastguard Worker         tls_set.Signal();
144*6777b538SAndroid Build Coastguard Worker       }));
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   tls_set.Wait();
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker   EXPECT_DCHECK_DEATH({ tls_owned_pointer.reset(); });
149*6777b538SAndroid Build Coastguard Worker }
150*6777b538SAndroid Build Coastguard Worker 
TEST(ThreadLocalTest,ThreadLocalOwnedPointerMultiThreadedAndStaticStorage)151*6777b538SAndroid Build Coastguard Worker TEST(ThreadLocalTest, ThreadLocalOwnedPointerMultiThreadedAndStaticStorage) {
152*6777b538SAndroid Build Coastguard Worker   constexpr int kNumThreads = 16;
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker   static ThreadLocalOwnedPointer<SetTrueOnDestruction> tls_owned_pointer;
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker   std::array<bool, kNumThreads> were_destroyed{};
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker   std::array<std::unique_ptr<Thread>, kNumThreads> threads;
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker   for (auto& thread : threads) {
161*6777b538SAndroid Build Coastguard Worker     thread = std::make_unique<Thread>("TestThread");
162*6777b538SAndroid Build Coastguard Worker     thread->Start();
163*6777b538SAndroid Build Coastguard Worker   }
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   for (const auto& thread : threads) {
166*6777b538SAndroid Build Coastguard Worker     // Waiting is unnecessary but enhances the likelihood of data races in the
167*6777b538SAndroid Build Coastguard Worker     // next steps.
168*6777b538SAndroid Build Coastguard Worker     thread->WaitUntilThreadStarted();
169*6777b538SAndroid Build Coastguard Worker   }
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker   for (const bool was_destroyed : were_destroyed) {
172*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(was_destroyed);
173*6777b538SAndroid Build Coastguard Worker   }
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kNumThreads; ++i) {
176*6777b538SAndroid Build Coastguard Worker     threads[i]->task_runner()->PostTask(
177*6777b538SAndroid Build Coastguard Worker         FROM_HERE,
178*6777b538SAndroid Build Coastguard Worker         BindOnce(
179*6777b538SAndroid Build Coastguard Worker             [](bool* was_destroyed) {
180*6777b538SAndroid Build Coastguard Worker               tls_owned_pointer.Set(
181*6777b538SAndroid Build Coastguard Worker                   std::make_unique<SetTrueOnDestruction>(was_destroyed));
182*6777b538SAndroid Build Coastguard Worker             },
183*6777b538SAndroid Build Coastguard Worker             &were_destroyed[i]));
184*6777b538SAndroid Build Coastguard Worker   }
185*6777b538SAndroid Build Coastguard Worker 
186*6777b538SAndroid Build Coastguard Worker   static bool main_thread_was_destroyed = false;
187*6777b538SAndroid Build Coastguard Worker   // Even when the test is run multiple times in the same process: TLS should
188*6777b538SAndroid Build Coastguard Worker   // never be destroyed until static uninitialization.
189*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(main_thread_was_destroyed);
190*6777b538SAndroid Build Coastguard Worker 
191*6777b538SAndroid Build Coastguard Worker   tls_owned_pointer.Set(
192*6777b538SAndroid Build Coastguard Worker       std::make_unique<SetTrueOnDestruction>(&main_thread_was_destroyed));
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker   for (const auto& thread : threads) {
195*6777b538SAndroid Build Coastguard Worker     thread->Stop();
196*6777b538SAndroid Build Coastguard Worker   }
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   for (const bool was_destroyed : were_destroyed) {
199*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(was_destroyed);
200*6777b538SAndroid Build Coastguard Worker   }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // The main thread's TLS still wasn't destroyed (let the test unfold naturally
203*6777b538SAndroid Build Coastguard Worker   // through static uninitialization).
204*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(main_thread_was_destroyed);
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker }  // namespace base
208