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