1 // Copyright (c) 2006-2008 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.
5 #include "base/logging.h"
6 #include "base/simple_thread.h"
7 #include "base/thread_local.h"
8 #include "base/waitable_event.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 class ThreadLocalTesterBase
: public base::DelegateSimpleThreadPool::Delegate
{
15 typedef base::ThreadLocalPointer
<ThreadLocalTesterBase
> TLPType
;
17 ThreadLocalTesterBase(TLPType
* tlp
, base::WaitableEvent
* done
)
18 : tlp_(tlp
), done_(done
) { }
19 ~ThreadLocalTesterBase() { }
23 base::WaitableEvent
* done_
;
26 class SetThreadLocal
: public ThreadLocalTesterBase
{
28 SetThreadLocal(TLPType
* tlp
, base::WaitableEvent
* done
)
29 : ThreadLocalTesterBase(tlp
, done
), val_(NULL
) { }
32 void set_value(ThreadLocalTesterBase
* val
) { val_
= val
; }
35 DCHECK(!done_
->IsSignaled());
41 ThreadLocalTesterBase
* val_
;
44 class GetThreadLocal
: public ThreadLocalTesterBase
{
46 GetThreadLocal(TLPType
* tlp
, base::WaitableEvent
* done
)
47 : ThreadLocalTesterBase(tlp
, done
), ptr_(NULL
) { }
50 void set_ptr(ThreadLocalTesterBase
** ptr
) { ptr_
= ptr
; }
53 DCHECK(!done_
->IsSignaled());
59 ThreadLocalTesterBase
** ptr_
;
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);
72 base::ThreadLocalPointer
<ThreadLocalTesterBase
> tlp
;
74 static ThreadLocalTesterBase
* const kBogusPointer
=
75 reinterpret_cast<ThreadLocalTesterBase
*>(0x1234);
77 ThreadLocalTesterBase
* tls_val
;
78 base::WaitableEvent
done(true, false);
80 GetThreadLocal
getter(&tlp
, &done
);
81 getter
.set_ptr(&tls_val
);
83 // Check that both threads defaulted to NULL.
84 tls_val
= kBogusPointer
;
88 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
90 tls_val
= kBogusPointer
;
94 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
97 SetThreadLocal
setter(&tlp
, &done
);
98 setter
.set_value(kBogusPointer
);
100 // Have thread 1 set their pointer value to kBogusPointer.
102 tp1
.AddWork(&setter
);
107 tp1
.AddWork(&getter
);
109 EXPECT_EQ(kBogusPointer
, tls_val
);
111 // Make sure thread 2 is still NULL
112 tls_val
= kBogusPointer
;
114 tp2
.AddWork(&getter
);
116 EXPECT_EQ(static_cast<ThreadLocalTesterBase
*>(NULL
), tls_val
);
118 // Set thread 2 to kBogusPointer + 1.
119 setter
.set_value(kBogusPointer
+ 1);
122 tp2
.AddWork(&setter
);
127 tp2
.AddWork(&getter
);
129 EXPECT_EQ(kBogusPointer
+ 1, tls_val
);
131 // Make sure thread 1 is still kBogusPointer.
134 tp1
.AddWork(&getter
);
136 EXPECT_EQ(kBogusPointer
, tls_val
);
142 TEST(ThreadLocalTest
, Boolean
) {
144 base::ThreadLocalBoolean tlb
;
145 EXPECT_EQ(false, tlb
.Get());
148 EXPECT_EQ(false, tlb
.Get());
151 EXPECT_EQ(true, tlb
.Get());
154 // Our slot should have been freed, we're all reset.
156 base::ThreadLocalBoolean tlb
;
157 EXPECT_EQ(false, tlb
.Get());