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.
5 #include "base/logging.h"
6 #include "base/threading/simple_thread.h"
7 #include "base/threading/thread_local.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 class ThreadLocalTesterBase
: public base::DelegateSimpleThreadPool::Delegate
{
17 typedef base::ThreadLocalPointer
<char> TLPType
;
19 ThreadLocalTesterBase(TLPType
* tlp
, base::WaitableEvent
* done
)
23 ~ThreadLocalTesterBase() override
{}
27 base::WaitableEvent
* done_
;
30 class SetThreadLocal
: public ThreadLocalTesterBase
{
32 SetThreadLocal(TLPType
* tlp
, base::WaitableEvent
* done
)
33 : ThreadLocalTesterBase(tlp
, done
),
36 ~SetThreadLocal() override
{}
38 void set_value(char* val
) { val_
= val
; }
41 DCHECK(!done_
->IsSignaled());
50 class GetThreadLocal
: public ThreadLocalTesterBase
{
52 GetThreadLocal(TLPType
* tlp
, base::WaitableEvent
* done
)
53 : ThreadLocalTesterBase(tlp
, done
),
56 ~GetThreadLocal() override
{}
58 void set_ptr(char** ptr
) { ptr_
= ptr
; }
61 DCHECK(!done_
->IsSignaled());
72 // In this test, we start 2 threads which will access a ThreadLocalPointer. We
73 // make sure the default is NULL, and the pointers are unique to the threads.
74 TEST(ThreadLocalTest
, Pointer
) {
75 base::DelegateSimpleThreadPool
tp1("ThreadLocalTest tp1", 1);
76 base::DelegateSimpleThreadPool
tp2("ThreadLocalTest tp1", 1);
80 base::ThreadLocalPointer
<char> tlp
;
82 static char* const kBogusPointer
= reinterpret_cast<char*>(0x1234);
85 base::WaitableEvent
done(true, false);
87 GetThreadLocal
getter(&tlp
, &done
);
88 getter
.set_ptr(&tls_val
);
90 // Check that both threads defaulted to NULL.
91 tls_val
= kBogusPointer
;
95 EXPECT_EQ(static_cast<char*>(NULL
), tls_val
);
97 tls_val
= kBogusPointer
;
101 EXPECT_EQ(static_cast<char*>(NULL
), tls_val
);
104 SetThreadLocal
setter(&tlp
, &done
);
105 setter
.set_value(kBogusPointer
);
107 // Have thread 1 set their pointer value to kBogusPointer.
109 tp1
.AddWork(&setter
);
114 tp1
.AddWork(&getter
);
116 EXPECT_EQ(kBogusPointer
, tls_val
);
118 // Make sure thread 2 is still NULL
119 tls_val
= kBogusPointer
;
121 tp2
.AddWork(&getter
);
123 EXPECT_EQ(static_cast<char*>(NULL
), tls_val
);
125 // Set thread 2 to kBogusPointer + 1.
126 setter
.set_value(kBogusPointer
+ 1);
129 tp2
.AddWork(&setter
);
134 tp2
.AddWork(&getter
);
136 EXPECT_EQ(kBogusPointer
+ 1, tls_val
);
138 // Make sure thread 1 is still kBogusPointer.
141 tp1
.AddWork(&getter
);
143 EXPECT_EQ(kBogusPointer
, tls_val
);
149 TEST(ThreadLocalTest
, Boolean
) {
151 base::ThreadLocalBoolean tlb
;
152 EXPECT_FALSE(tlb
.Get());
155 EXPECT_FALSE(tlb
.Get());
158 EXPECT_TRUE(tlb
.Get());
161 // Our slot should have been freed, we're all reset.
163 base::ThreadLocalBoolean tlb
;
164 EXPECT_FALSE(tlb
.Get());