blob: 54f2ad236b079b267c90b41db626a684bb218089 [file] [log] [blame]
[email protected]44106182012-04-06 03:53:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]83a05dd2008-09-03 16:47:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/logging.h"
[email protected]ac9ba8fe2010-12-30 18:08:366#include "base/threading/simple_thread.h"
[email protected]1357c322010-12-30 22:18:567#include "base/threading/thread_local.h"
[email protected]44f9c952011-01-02 06:05:398#include "base/synchronization/waitable_event.h"
[email protected]83a05dd2008-09-03 16:47:379#include "testing/gtest/include/gtest/gtest.h"
10
[email protected]1357c322010-12-30 22:18:5611namespace base {
12
[email protected]83a05dd2008-09-03 16:47:3713namespace {
14
15class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
16 public:
pcc5b3c85ae2015-03-31 19:08:1517 typedef base::ThreadLocalPointer<char> TLPType;
[email protected]83a05dd2008-09-03 16:47:3718
19 ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
[email protected]44106182012-04-06 03:53:0220 : tlp_(tlp),
21 done_(done) {
22 }
Chris Watkinsbb7211c2017-11-29 07:16:3823 ~ThreadLocalTesterBase() override = default;
[email protected]83a05dd2008-09-03 16:47:3724
25 protected:
26 TLPType* tlp_;
27 base::WaitableEvent* done_;
28};
29
30class SetThreadLocal : public ThreadLocalTesterBase {
31 public:
32 SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
Ivan Kotenkova16212a52017-11-08 12:37:3333 : ThreadLocalTesterBase(tlp, done), val_(nullptr) {}
Chris Watkinsbb7211c2017-11-29 07:16:3834 ~SetThreadLocal() override = default;
[email protected]52a261f2009-03-03 15:01:1235
pcc5b3c85ae2015-03-31 19:08:1536 void set_value(char* val) { val_ = val; }
[email protected]83a05dd2008-09-03 16:47:3737
dcheng56488182014-10-21 10:54:5138 void Run() override {
[email protected]83a05dd2008-09-03 16:47:3739 DCHECK(!done_->IsSignaled());
40 tlp_->Set(val_);
41 done_->Signal();
42 }
43
44 private:
pcc5b3c85ae2015-03-31 19:08:1545 char* val_;
[email protected]83a05dd2008-09-03 16:47:3746};
47
48class GetThreadLocal : public ThreadLocalTesterBase {
49 public:
50 GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
Ivan Kotenkova16212a52017-11-08 12:37:3351 : ThreadLocalTesterBase(tlp, done), ptr_(nullptr) {}
Chris Watkinsbb7211c2017-11-29 07:16:3852 ~GetThreadLocal() override = default;
[email protected]52a261f2009-03-03 15:01:1253
pcc5b3c85ae2015-03-31 19:08:1554 void set_ptr(char** ptr) { ptr_ = ptr; }
[email protected]83a05dd2008-09-03 16:47:3755
dcheng56488182014-10-21 10:54:5156 void Run() override {
[email protected]83a05dd2008-09-03 16:47:3757 DCHECK(!done_->IsSignaled());
58 *ptr_ = tlp_->Get();
59 done_->Signal();
60 }
61
62 private:
pcc5b3c85ae2015-03-31 19:08:1563 char** ptr_;
[email protected]83a05dd2008-09-03 16:47:3764};
65
66} // namespace
67
68// In this test, we start 2 threads which will access a ThreadLocalPointer. We
69// make sure the default is NULL, and the pointers are unique to the threads.
70TEST(ThreadLocalTest, Pointer) {
71 base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
72 base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
73 tp1.Start();
74 tp2.Start();
75
pcc5b3c85ae2015-03-31 19:08:1576 base::ThreadLocalPointer<char> tlp;
[email protected]52a261f2009-03-03 15:01:1277
pcc5b3c85ae2015-03-31 19:08:1578 static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
[email protected]83a05dd2008-09-03 16:47:3779
pcc5b3c85ae2015-03-31 19:08:1580 char* tls_val;
gab75d72332016-06-01 21:15:3381 base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
82 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]83a05dd2008-09-03 16:47:3783
84 GetThreadLocal getter(&tlp, &done);
85 getter.set_ptr(&tls_val);
86
87 // Check that both threads defaulted to NULL.
88 tls_val = kBogusPointer;
89 done.Reset();
90 tp1.AddWork(&getter);
91 done.Wait();
Ivan Kotenkova16212a52017-11-08 12:37:3392 EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
[email protected]83a05dd2008-09-03 16:47:3793
94 tls_val = kBogusPointer;
95 done.Reset();
96 tp2.AddWork(&getter);
97 done.Wait();
Ivan Kotenkova16212a52017-11-08 12:37:3398 EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
[email protected]83a05dd2008-09-03 16:47:3799
100 SetThreadLocal setter(&tlp, &done);
101 setter.set_value(kBogusPointer);
102
103 // Have thread 1 set their pointer value to kBogusPointer.
104 done.Reset();
105 tp1.AddWork(&setter);
106 done.Wait();
107
Ivan Kotenkova16212a52017-11-08 12:37:33108 tls_val = nullptr;
[email protected]83a05dd2008-09-03 16:47:37109 done.Reset();
110 tp1.AddWork(&getter);
111 done.Wait();
112 EXPECT_EQ(kBogusPointer, tls_val);
113
114 // Make sure thread 2 is still NULL
115 tls_val = kBogusPointer;
116 done.Reset();
117 tp2.AddWork(&getter);
118 done.Wait();
Ivan Kotenkova16212a52017-11-08 12:37:33119 EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
[email protected]83a05dd2008-09-03 16:47:37120
121 // Set thread 2 to kBogusPointer + 1.
122 setter.set_value(kBogusPointer + 1);
123
124 done.Reset();
125 tp2.AddWork(&setter);
126 done.Wait();
127
Ivan Kotenkova16212a52017-11-08 12:37:33128 tls_val = nullptr;
[email protected]83a05dd2008-09-03 16:47:37129 done.Reset();
130 tp2.AddWork(&getter);
131 done.Wait();
132 EXPECT_EQ(kBogusPointer + 1, tls_val);
133
134 // Make sure thread 1 is still kBogusPointer.
Ivan Kotenkova16212a52017-11-08 12:37:33135 tls_val = nullptr;
[email protected]83a05dd2008-09-03 16:47:37136 done.Reset();
137 tp1.AddWork(&getter);
138 done.Wait();
139 EXPECT_EQ(kBogusPointer, tls_val);
140
141 tp1.JoinAll();
142 tp2.JoinAll();
143}
144
145TEST(ThreadLocalTest, Boolean) {
146 {
147 base::ThreadLocalBoolean tlb;
[email protected]34f40942010-10-04 00:34:04148 EXPECT_FALSE(tlb.Get());
[email protected]83a05dd2008-09-03 16:47:37149
150 tlb.Set(false);
[email protected]34f40942010-10-04 00:34:04151 EXPECT_FALSE(tlb.Get());
[email protected]83a05dd2008-09-03 16:47:37152
153 tlb.Set(true);
[email protected]34f40942010-10-04 00:34:04154 EXPECT_TRUE(tlb.Get());
[email protected]83a05dd2008-09-03 16:47:37155 }
156
157 // Our slot should have been freed, we're all reset.
158 {
159 base::ThreadLocalBoolean tlb;
[email protected]34f40942010-10-04 00:34:04160 EXPECT_FALSE(tlb.Get());
[email protected]83a05dd2008-09-03 16:47:37161 }
162}
[email protected]1357c322010-12-30 22:18:56163
164} // namespace base