1 // Copyright (c) 2006-2008 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.
10 #include "base/simple_thread.h"
11 #include "base/thread_local_storage.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 // Ignore warnings about ptr->int conversions that we use when
16 // storing ints into ThreadLocalStorage.
17 #pragma warning(disable : 4311 4312)
20 const int kInitialTlsValue
= 0x5555;
21 static ThreadLocalStorage::Slot
tls_slot(base::LINKER_INITIALIZED
);
24 class ThreadLocalStorageRunner
: public base::DelegateSimpleThread::Delegate
{
26 explicit ThreadLocalStorageRunner(int* tls_value_ptr
)
27 : tls_value_ptr_(tls_value_ptr
) {}
29 virtual ~ThreadLocalStorageRunner() {}
32 *tls_value_ptr_
= kInitialTlsValue
;
33 tls_slot
.Set(tls_value_ptr_
);
35 int *ptr
= static_cast<int*>(tls_slot
.Get());
36 EXPECT_EQ(ptr
, tls_value_ptr_
);
37 EXPECT_EQ(*ptr
, kInitialTlsValue
);
40 ptr
= static_cast<int*>(tls_slot
.Get());
41 EXPECT_EQ(ptr
, tls_value_ptr_
);
47 DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorageRunner
);
51 void ThreadLocalStorageCleanup(void *value
) {
52 int *ptr
= reinterpret_cast<int*>(value
);
54 *ptr
= kInitialTlsValue
;
58 TEST(ThreadLocalStorageTest
, Basics
) {
59 ThreadLocalStorage::Slot slot
;
60 slot
.Set(reinterpret_cast<void*>(123));
61 int value
= reinterpret_cast<intptr_t>(slot
.Get());
62 EXPECT_EQ(value
, 123);
65 TEST(ThreadLocalStorageTest
, TLSDestructors
) {
66 // Create a TLS index with a destructor. Create a set of
67 // threads that set the TLS, while the destructor cleans it up.
68 // After the threads finish, verify that the value is cleaned up.
69 const int kNumThreads
= 5;
70 int values
[kNumThreads
];
71 ThreadLocalStorageRunner
* thread_delegates
[kNumThreads
];
72 base::DelegateSimpleThread
* threads
[kNumThreads
];
74 tls_slot
.Initialize(ThreadLocalStorageCleanup
);
77 for (int index
= 0; index
< kNumThreads
; index
++) {
78 values
[index
] = kInitialTlsValue
;
79 thread_delegates
[index
] = new ThreadLocalStorageRunner(&values
[index
]);
80 threads
[index
] = new base::DelegateSimpleThread(thread_delegates
[index
],
82 threads
[index
]->Start();
85 // Wait for the threads to finish.
86 for (int index
= 0; index
< kNumThreads
; index
++) {
87 threads
[index
]->Join();
88 delete threads
[index
];
89 delete thread_delegates
[index
];
91 // Verify that the destructor was called and that we reset.
92 EXPECT_EQ(values
[index
], kInitialTlsValue
);