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 |