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 20namespace base { 21 22namespace { 23 24const int kInitialTlsValue = 0x5555; 25static ThreadLocalStorage::Slot tls_slot(LINKER_INITIALIZED); 26 27class 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 54void ThreadLocalStorageCleanup(void *value) { 55 int *ptr = reinterpret_cast<int*>(value); 56 if (ptr) 57 *ptr = kInitialTlsValue; 58} 59 60} // namespace 61 62TEST(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 69TEST(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