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