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