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 |