thread_local_storage_unittest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
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