|
1 // Copyright (c) 2011 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 // WARNING: Thread local storage is a bit tricky to get right. Please make |
|
6 // sure that this is really the proper solution for what you're trying to |
|
7 // achieve. Don't prematurely optimize, most likely you can just use a Lock. |
|
8 // |
|
9 // These classes implement a wrapper around the platform's TLS storage |
|
10 // mechanism. On construction, they will allocate a TLS slot, and free the |
|
11 // TLS slot on destruction. No memory management (creation or destruction) is |
|
12 // handled. This means for uses of ThreadLocalPointer, you must correctly |
|
13 // manage the memory yourself, these classes will not destroy the pointer for |
|
14 // you. There are no at-thread-exit actions taken by these classes. |
|
15 // |
|
16 // ThreadLocalPointer<Type> wraps a Type*. It performs no creation or |
|
17 // destruction, so memory management must be handled elsewhere. The first call |
|
18 // to Get() on a thread will return NULL. You can update the pointer with a |
|
19 // call to Set(). |
|
20 // |
|
21 // ThreadLocalBoolean wraps a bool. It will default to false if it has never |
|
22 // been set otherwise with Set(). |
|
23 // |
|
24 // Thread Safety: An instance of ThreadLocalStorage is completely thread safe |
|
25 // once it has been created. If you want to dynamically create an instance, |
|
26 // you must of course properly deal with safety and race conditions. This |
|
27 // means a function-level static initializer is generally inappropiate. |
|
28 // |
|
29 // Example usage: |
|
30 // // My class is logically attached to a single thread. We cache a pointer |
|
31 // // on the thread it was created on, so we can implement current(). |
|
32 // MyClass::MyClass() { |
|
33 // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL); |
|
34 // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this); |
|
35 // } |
|
36 // |
|
37 // MyClass::~MyClass() { |
|
38 // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL); |
|
39 // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL); |
|
40 // } |
|
41 // |
|
42 // // Return the current MyClass associated with the calling thread, can be |
|
43 // // NULL if there isn't a MyClass associated. |
|
44 // MyClass* MyClass::current() { |
|
45 // return Singleton<ThreadLocalPointer<MyClass> >::get()->Get(); |
|
46 // } |
|
47 |
|
48 #ifndef BASE_THREADING_THREAD_LOCAL_H_ |
|
49 #define BASE_THREADING_THREAD_LOCAL_H_ |
|
50 |
|
51 #include "base/base_export.h" |
|
52 #include "base/basictypes.h" |
|
53 |
|
54 #if defined(OS_POSIX) |
|
55 #include <pthread.h> |
|
56 #endif |
|
57 |
|
58 namespace base { |
|
59 |
|
60 namespace internal { |
|
61 |
|
62 // Helper functions that abstract the cross-platform APIs. Do not use directly. |
|
63 struct BASE_EXPORT ThreadLocalPlatform { |
|
64 #if defined(OS_WIN) |
|
65 typedef unsigned long SlotType; |
|
66 #elif defined(OS_POSIX) |
|
67 typedef pthread_key_t SlotType; |
|
68 #endif |
|
69 |
|
70 static void AllocateSlot(SlotType& slot); |
|
71 static void FreeSlot(SlotType& slot); |
|
72 static void* GetValueFromSlot(SlotType& slot); |
|
73 static void SetValueInSlot(SlotType& slot, void* value); |
|
74 }; |
|
75 |
|
76 } // namespace internal |
|
77 |
|
78 template <typename Type> |
|
79 class ThreadLocalPointer { |
|
80 public: |
|
81 ThreadLocalPointer() : slot_() { |
|
82 internal::ThreadLocalPlatform::AllocateSlot(slot_); |
|
83 } |
|
84 |
|
85 ~ThreadLocalPointer() { |
|
86 internal::ThreadLocalPlatform::FreeSlot(slot_); |
|
87 } |
|
88 |
|
89 Type* Get() { |
|
90 return static_cast<Type*>( |
|
91 internal::ThreadLocalPlatform::GetValueFromSlot(slot_)); |
|
92 } |
|
93 |
|
94 void Set(Type* ptr) { |
|
95 internal::ThreadLocalPlatform::SetValueInSlot( |
|
96 slot_, const_cast<void*>(static_cast<const void*>(ptr))); |
|
97 } |
|
98 |
|
99 private: |
|
100 typedef internal::ThreadLocalPlatform::SlotType SlotType; |
|
101 |
|
102 SlotType slot_; |
|
103 |
|
104 DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); |
|
105 }; |
|
106 |
|
107 class ThreadLocalBoolean { |
|
108 public: |
|
109 ThreadLocalBoolean() { } |
|
110 ~ThreadLocalBoolean() { } |
|
111 |
|
112 bool Get() { |
|
113 return tlp_.Get() != NULL; |
|
114 } |
|
115 |
|
116 void Set(bool val) { |
|
117 tlp_.Set(val ? this : NULL); |
|
118 } |
|
119 |
|
120 private: |
|
121 ThreadLocalPointer<void> tlp_; |
|
122 |
|
123 DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean); |
|
124 }; |
|
125 |
|
126 } // namespace base |
|
127 |
|
128 #endif // BASE_THREADING_THREAD_LOCAL_H_ |