|
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. |
|
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 warpper 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_THREAD_LOCAL_H_ |
|
49 #define BASE_THREAD_LOCAL_H_ |
|
50 |
|
51 #include "base/basictypes.h" |
|
52 |
|
53 #if defined(OS_POSIX) |
|
54 #include <pthread.h> |
|
55 #endif |
|
56 |
|
57 namespace base { |
|
58 |
|
59 // Helper functions that abstract the cross-platform APIs. Do not use directly. |
|
60 struct ThreadLocalPlatform { |
|
61 #if defined(OS_WIN) |
|
62 typedef int SlotType; |
|
63 #elif defined(OS_POSIX) |
|
64 typedef pthread_key_t SlotType; |
|
65 #endif |
|
66 |
|
67 static void AllocateSlot(SlotType& slot); |
|
68 static void FreeSlot(SlotType& slot); |
|
69 static void* GetValueFromSlot(SlotType& slot); |
|
70 static void SetValueInSlot(SlotType& slot, void* value); |
|
71 }; |
|
72 |
|
73 template <typename Type> |
|
74 class ThreadLocalPointer { |
|
75 public: |
|
76 ThreadLocalPointer() : slot_() { |
|
77 ThreadLocalPlatform::AllocateSlot(slot_); |
|
78 } |
|
79 |
|
80 ~ThreadLocalPointer() { |
|
81 ThreadLocalPlatform::FreeSlot(slot_); |
|
82 } |
|
83 |
|
84 Type* Get() { |
|
85 return static_cast<Type*>(ThreadLocalPlatform::GetValueFromSlot(slot_)); |
|
86 } |
|
87 |
|
88 void Set(Type* ptr) { |
|
89 ThreadLocalPlatform::SetValueInSlot(slot_, ptr); |
|
90 } |
|
91 |
|
92 private: |
|
93 typedef ThreadLocalPlatform::SlotType SlotType; |
|
94 |
|
95 SlotType slot_; |
|
96 |
|
97 DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); |
|
98 }; |
|
99 |
|
100 class ThreadLocalBoolean { |
|
101 public: |
|
102 ThreadLocalBoolean() { } |
|
103 ~ThreadLocalBoolean() { } |
|
104 |
|
105 bool Get() { |
|
106 return tlp_.Get() != NULL; |
|
107 } |
|
108 |
|
109 void Set(bool val) { |
|
110 tlp_.Set(reinterpret_cast<void*>(val ? 1 : 0)); |
|
111 } |
|
112 |
|
113 private: |
|
114 ThreadLocalPointer<void> tlp_; |
|
115 |
|
116 DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean); |
|
117 }; |
|
118 |
|
119 } // namespace base |
|
120 |
|
121 #endif // BASE_THREAD_LOCAL_H_ |