15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/simple_thread.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_local.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : tlp_(tlp), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_(done) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ThreadLocalTesterBase() {} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TLPType* tlp_; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* done_; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SetThreadLocal : public ThreadLocalTesterBase { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetThreadLocal(TLPType* tlp, base::WaitableEvent* done) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ThreadLocalTesterBase(tlp, done), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val_(NULL) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SetThreadLocal() {} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_value(ThreadLocalTesterBase* val) { val_ = val; } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!done_->IsSignaled()); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tlp_->Set(val_); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_->Signal(); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadLocalTesterBase* val_; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GetThreadLocal : public ThreadLocalTesterBase { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetThreadLocal(TLPType* tlp, base::WaitableEvent* done) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ThreadLocalTesterBase(tlp, done), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr_(NULL) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GetThreadLocal() {} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!done_->IsSignaled()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr_ = tlp_->Get(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_->Signal(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadLocalTesterBase** ptr_; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In this test, we start 2 threads which will access a ThreadLocalPointer. We 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// make sure the default is NULL, and the pointers are unique to the threads. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ThreadLocalTest, Pointer) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.Start(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.Start(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadLocalPointer<ThreadLocalTesterBase> tlp; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ThreadLocalTesterBase* const kBogusPointer = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ThreadLocalTesterBase*>(0x1234); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadLocalTesterBase* tls_val; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent done(true, false); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetThreadLocal getter(&tlp, &done); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getter.set_ptr(&tls_val); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that both threads defaulted to NULL. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = kBogusPointer; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.AddWork(&getter); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = kBogusPointer; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.AddWork(&getter); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetThreadLocal setter(&tlp, &done); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setter.set_value(kBogusPointer); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have thread 1 set their pointer value to kBogusPointer. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.AddWork(&setter); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = NULL; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.AddWork(&getter); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kBogusPointer, tls_val); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure thread 2 is still NULL 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = kBogusPointer; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.AddWork(&getter); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set thread 2 to kBogusPointer + 1. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setter.set_value(kBogusPointer + 1); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.AddWork(&setter); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = NULL; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.AddWork(&getter); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kBogusPointer + 1, tls_val); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure thread 1 is still kBogusPointer. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tls_val = NULL; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Reset(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.AddWork(&getter); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kBogusPointer, tls_val); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp1.JoinAll(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp2.JoinAll(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ThreadLocalTest, Boolean) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadLocalBoolean tlb; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(tlb.Get()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tlb.Set(false); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(tlb.Get()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tlb.Set(true); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(tlb.Get()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our slot should have been freed, we're all reset. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadLocalBoolean tlb; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(tlb.Get()); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 170