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 #if defined(OS_WIN) 6 #include <windows.h> 7 #include <process.h> 8 #endif 9 10 #include "base/threading/simple_thread.h" 11 #include "base/threading/thread_local_storage.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 #if defined(OS_WIN) 15 // Ignore warnings about ptr->int conversions that we use when 16 // storing ints into ThreadLocalStorage. 17 #pragma warning(disable : 4311 4312) 18 #endif 19 20 namespace base { 21 22 namespace { 23 24 const int kInitialTlsValue = 0x5555; 25 static ThreadLocalStorage::Slot tls_slot(LINKER_INITIALIZED); 26 27 class ThreadLocalStorageRunner : public DelegateSimpleThread::Delegate { 28 public: 29 explicit ThreadLocalStorageRunner(int* tls_value_ptr) 30 : tls_value_ptr_(tls_value_ptr) {} 31 32 virtual ~ThreadLocalStorageRunner() {} 33 34 virtual void Run() { 35 *tls_value_ptr_ = kInitialTlsValue; 36 tls_slot.Set(tls_value_ptr_); 37 38 int *ptr = static_cast<int*>(tls_slot.Get()); 39 EXPECT_EQ(ptr, tls_value_ptr_); 40 EXPECT_EQ(*ptr, kInitialTlsValue); 41 *tls_value_ptr_ = 0; 42 43 ptr = static_cast<int*>(tls_slot.Get()); 44 EXPECT_EQ(ptr, tls_value_ptr_); 45 EXPECT_EQ(*ptr, 0); 46 } 47 48 private: 49 int* tls_value_ptr_; 50 DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorageRunner); 51 }; 52 53 54 void ThreadLocalStorageCleanup(void *value) { 55 int *ptr = reinterpret_cast<int*>(value); 56 if (ptr) 57 *ptr = kInitialTlsValue; 58 } 59 60 } // namespace 61 62 TEST(ThreadLocalStorageTest, Basics) { 63 ThreadLocalStorage::Slot slot; 64 slot.Set(reinterpret_cast<void*>(123)); 65 int value = reinterpret_cast<intptr_t>(slot.Get()); 66 EXPECT_EQ(value, 123); 67 } 68 69 TEST(ThreadLocalStorageTest, TLSDestructors) { 70 // Create a TLS index with a destructor. Create a set of 71 // threads that set the TLS, while the destructor cleans it up. 72 // After the threads finish, verify that the value is cleaned up. 73 const int kNumThreads = 5; 74 int values[kNumThreads]; 75 ThreadLocalStorageRunner* thread_delegates[kNumThreads]; 76 DelegateSimpleThread* threads[kNumThreads]; 77 78 tls_slot.Initialize(ThreadLocalStorageCleanup); 79 80 // Spawn the threads. 81 for (int index = 0; index < kNumThreads; index++) { 82 values[index] = kInitialTlsValue; 83 thread_delegates[index] = new ThreadLocalStorageRunner(&values[index]); 84 threads[index] = new DelegateSimpleThread(thread_delegates[index], 85 "tls thread"); 86 threads[index]->Start(); 87 } 88 89 // Wait for the threads to finish. 90 for (int index = 0; index < kNumThreads; index++) { 91 threads[index]->Join(); 92 delete threads[index]; 93 delete thread_delegates[index]; 94 95 // Verify that the destructor was called and that we reset. 96 EXPECT_EQ(values[index], kInitialTlsValue); 97 } 98 } 99 100 } // namespace base 101