1 // Copyright (c) 2010 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. 4 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" 10 11 namespace base { 12 13 namespace { 14 15 class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate { 16 public: 17 typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType; 18 19 ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done) 20 : tlp_(tlp), done_(done) { } 21 ~ThreadLocalTesterBase() { } 22 23 protected: 24 TLPType* tlp_; 25 base::WaitableEvent* done_; 26 }; 27 28 class SetThreadLocal : public ThreadLocalTesterBase { 29 public: 30 SetThreadLocal(TLPType* tlp, base::WaitableEvent* done) 31 : ThreadLocalTesterBase(tlp, done), val_(NULL) { } 32 ~SetThreadLocal() { } 33 34 void set_value(ThreadLocalTesterBase* val) { val_ = val; } 35 36 virtual void Run() { 37 DCHECK(!done_->IsSignaled()); 38 tlp_->Set(val_); 39 done_->Signal(); 40 } 41 42 private: 43 ThreadLocalTesterBase* val_; 44 }; 45 46 class GetThreadLocal : public ThreadLocalTesterBase { 47 public: 48 GetThreadLocal(TLPType* tlp, base::WaitableEvent* done) 49 : ThreadLocalTesterBase(tlp, done), ptr_(NULL) { } 50 ~GetThreadLocal() { } 51 52 void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; } 53 54 virtual void Run() { 55 DCHECK(!done_->IsSignaled()); 56 *ptr_ = tlp_->Get(); 57 done_->Signal(); 58 } 59 60 private: 61 ThreadLocalTesterBase** ptr_; 62 }; 63 64 } // namespace 65 66 // In this test, we start 2 threads which will access a ThreadLocalPointer. We 67 // make sure the default is NULL, and the pointers are unique to the threads. 68 TEST(ThreadLocalTest, Pointer) { 69 base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1); 70 base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1); 71 tp1.Start(); 72 tp2.Start(); 73 74 base::ThreadLocalPointer<ThreadLocalTesterBase> tlp; 75 76 static ThreadLocalTesterBase* const kBogusPointer = 77 reinterpret_cast<ThreadLocalTesterBase*>(0x1234); 78 79 ThreadLocalTesterBase* tls_val; 80 base::WaitableEvent done(true, false); 81 82 GetThreadLocal getter(&tlp, &done); 83 getter.set_ptr(&tls_val); 84 85 // Check that both threads defaulted to NULL. 86 tls_val = kBogusPointer; 87 done.Reset(); 88 tp1.AddWork(&getter); 89 done.Wait(); 90 EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 91 92 tls_val = kBogusPointer; 93 done.Reset(); 94 tp2.AddWork(&getter); 95 done.Wait(); 96 EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 97 98 99 SetThreadLocal setter(&tlp, &done); 100 setter.set_value(kBogusPointer); 101 102 // Have thread 1 set their pointer value to kBogusPointer. 103 done.Reset(); 104 tp1.AddWork(&setter); 105 done.Wait(); 106 107 tls_val = NULL; 108 done.Reset(); 109 tp1.AddWork(&getter); 110 done.Wait(); 111 EXPECT_EQ(kBogusPointer, tls_val); 112 113 // Make sure thread 2 is still NULL 114 tls_val = kBogusPointer; 115 done.Reset(); 116 tp2.AddWork(&getter); 117 done.Wait(); 118 EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 119 120 // Set thread 2 to kBogusPointer + 1. 121 setter.set_value(kBogusPointer + 1); 122 123 done.Reset(); 124 tp2.AddWork(&setter); 125 done.Wait(); 126 127 tls_val = NULL; 128 done.Reset(); 129 tp2.AddWork(&getter); 130 done.Wait(); 131 EXPECT_EQ(kBogusPointer + 1, tls_val); 132 133 // Make sure thread 1 is still kBogusPointer. 134 tls_val = NULL; 135 done.Reset(); 136 tp1.AddWork(&getter); 137 done.Wait(); 138 EXPECT_EQ(kBogusPointer, tls_val); 139 140 tp1.JoinAll(); 141 tp2.JoinAll(); 142 } 143 144 TEST(ThreadLocalTest, Boolean) { 145 { 146 base::ThreadLocalBoolean tlb; 147 EXPECT_FALSE(tlb.Get()); 148 149 tlb.Set(false); 150 EXPECT_FALSE(tlb.Get()); 151 152 tlb.Set(true); 153 EXPECT_TRUE(tlb.Get()); 154 } 155 156 // Our slot should have been freed, we're all reset. 157 { 158 base::ThreadLocalBoolean tlb; 159 EXPECT_FALSE(tlb.Get()); 160 } 161 } 162 163 } // namespace base 164