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
<ThreadLocalTesterBase
> 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(ThreadLocalTesterBase
* val
) { val_
= val
; }
41 DCHECK(!done_
->IsSignaled());
47 ThreadLocalTesterBase
* val_
;
50 class GetThreadLocal
: public ThreadLocalTesterBase
{
52 GetThreadLocal(TLPType
* tlp
, base::WaitableEvent
* done
)
53 : ThreadLocalTesterBase(tlp
, done
),
56 ~GetThreadLocal() override
{}
58 void set_ptr(ThreadLocalTesterBase
** ptr
) { ptr_
= ptr
; }
61 DCHECK(!done_
->IsSignaled());
67 ThreadLocalTesterBase
** ptr_
;
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
<ThreadLocalTesterBase
> tlp
;
82 static ThreadLocalTesterBase
* const kBogusPointer
=
83 reinterpret_cast<ThreadLocalTesterBase
*>(0x1234);
85 ThreadLocalTesterBase
* tls_val
;
86 base::WaitableEvent
done(true, false);
88 GetThreadLocal
getter(&tlp
, &done
);
89 getter
.set_ptr(&tls_val
);
91 // Check that both threads defaulted to NULL.
92 tls_val
= kBogusPointer
;
96 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
98 tls_val
= kBogusPointer
;
100 tp2
.AddWork(&getter
);
102 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
105 SetThreadLocal
setter(&tlp
, &done
);
106 setter
.set_value(kBogusPointer
);
108 // Have thread 1 set their pointer value to kBogusPointer.
110 tp1
.AddWork(&setter
);
115 tp1
.AddWork(&getter
);
117 EXPECT_EQ(kBogusPointer
, tls_val
);
119 // Make sure thread 2 is still NULL
120 tls_val
= kBogusPointer
;
122 tp2
.AddWork(&getter
);
124 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
126 // Set thread 2 to kBogusPointer + 1.
127 setter
.set_value(kBogusPointer
+ 1);
130 tp2
.AddWork(&setter
);
135 tp2
.AddWork(&getter
);
137 EXPECT_EQ(kBogusPointer
+ 1, tls_val
);
139 // Make sure thread 1 is still kBogusPointer.
142 tp1
.AddWork(&getter
);
144 EXPECT_EQ(kBogusPointer
, tls_val
);
150 TEST(ThreadLocalTest
, Boolean
) {
152 base::ThreadLocalBoolean tlb
;
153 EXPECT_FALSE(tlb
.Get());
156 EXPECT_FALSE(tlb
.Get());
159 EXPECT_TRUE(tlb
.Get());
162 // Our slot should have been freed, we're all reset.
164 base::ThreadLocalBoolean tlb
;
165 EXPECT_FALSE(tlb
.Get());