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