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 virtual ~ThreadLocalTesterBase() {}
27 base::WaitableEvent* done_;
30 class SetThreadLocal : public ThreadLocalTesterBase {
32 SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
33 : ThreadLocalTesterBase(tlp, done),
36 virtual ~SetThreadLocal() {}
38 void set_value(ThreadLocalTesterBase* val) { val_ = val; }
40 virtual void Run() OVERRIDE {
41 DCHECK(!done_->IsSignaled());
47 ThreadLocalTesterBase* val_;
50 class GetThreadLocal : public ThreadLocalTesterBase {
52 GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
53 : ThreadLocalTesterBase(tlp, done),
56 virtual ~GetThreadLocal() {}
58 void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
60 virtual void Run() OVERRIDE {
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());