Index: base/threading/thread_local.h |
diff --git a/base/threading/thread_local.h b/base/threading/thread_local.h |
index cad9add3a9ca344ec03b75a8be150370d509ba1a..f40420cd2f8b8276e643b08ab294e8bdfba92b24 100644 |
--- a/base/threading/thread_local.h |
+++ b/base/threading/thread_local.h |
@@ -2,34 +2,35 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-// WARNING: Thread local storage is a bit tricky to get right. Please make sure |
-// that this is really the proper solution for what you're trying to achieve. |
-// Don't prematurely optimize, most likely you can just use a Lock. |
+// WARNING: Thread local storage is a bit tricky to get right. Please make |
+// sure that this is really the proper solution for what you're trying to |
+// achieve. Don't prematurely optimize, most likely you can just use a Lock. |
// |
-// These classes implement a wrapper around ThreadLocalStorage::Slot. On |
-// construction, they will allocate a TLS slot, and free the TLS slot on |
-// destruction. No memory management (creation or destruction) is handled. This |
-// means for uses of ThreadLocalPointer, you must correctly manage the memory |
-// yourself, these classes will not destroy the pointer for you. There are no |
-// at-thread-exit actions taken by these classes. |
+// These classes implement a wrapper around the platform's TLS storage |
+// mechanism. On construction, they will allocate a TLS slot, and free the |
+// TLS slot on destruction. No memory management (creation or destruction) is |
+// handled. This means for uses of ThreadLocalPointer, you must correctly |
+// manage the memory yourself, these classes will not destroy the pointer for |
+// you. There are no at-thread-exit actions taken by these classes. |
// |
-// ThreadLocalPointer<Type> wraps a Type*. It performs no creation or |
-// destruction, so memory management must be handled elsewhere. The first call |
-// to Get() on a thread will return NULL. You can update the pointer with a call |
-// to Set(). |
+// ThreadLocalPointer<Type> wraps a Type*. It performs no creation or |
+// destruction, so memory management must be handled elsewhere. The first call |
+// to Get() on a thread will return NULL. You can update the pointer with a |
+// call to Set(). |
// |
-// ThreadLocalBoolean wraps a bool. It will default to false if it has never |
+// ThreadLocalBoolean wraps a bool. It will default to false if it has never |
// been set otherwise with Set(). |
// |
-// Thread Safety: An instance of ThreadLocalStorage is completely thread safe |
-// once it has been created. If you want to dynamically create an instance, you |
-// must of course properly deal with safety and race conditions. This means a |
-// function-level static initializer is generally inappropiate. |
+// Thread Safety: An instance of ThreadLocalStorage is completely thread safe |
+// once it has been created. If you want to dynamically create an instance, |
+// you must of course properly deal with safety and race conditions. This |
+// means a function-level static initializer is generally inappropiate. |
// |
-// In Android, the system TLS is limited. |
+// In Android, the system TLS is limited, the implementation is backed with |
+// ThreadLocalStorage. |
// |
// Example usage: |
-// // My class is logically attached to a single thread. We cache a pointer |
+// // My class is logically attached to a single thread. We cache a pointer |
// // on the thread it was created on, so we can implement current(). |
// MyClass::MyClass() { |
// DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL); |
@@ -50,42 +51,76 @@ |
#ifndef BASE_THREADING_THREAD_LOCAL_H_ |
#define BASE_THREADING_THREAD_LOCAL_H_ |
+#include "base/base_export.h" |
#include "base/macros.h" |
#include "base/threading/thread_local_storage.h" |
+#include "build/build_config.h" |
+ |
+#if defined(OS_POSIX) |
+#include <pthread.h> |
+#endif |
namespace base { |
+namespace internal { |
+ |
+// Helper functions that abstract the cross-platform APIs. Do not use directly. |
+struct BASE_EXPORT ThreadLocalPlatform { |
+#if defined(OS_WIN) |
+ typedef unsigned long SlotType; |
+#elif defined(OS_ANDROID) |
+ typedef ThreadLocalStorage::StaticSlot SlotType; |
+#elif defined(OS_POSIX) |
+ typedef pthread_key_t SlotType; |
+#endif |
+ |
+ static void AllocateSlot(SlotType* slot); |
+ static void FreeSlot(SlotType slot); |
+ static void* GetValueFromSlot(SlotType slot); |
+ static void SetValueInSlot(SlotType slot, void* value); |
+}; |
+ |
+} // namespace internal |
template <typename Type> |
class ThreadLocalPointer { |
public: |
- ThreadLocalPointer() = default; |
- ~ThreadLocalPointer() = default; |
+ ThreadLocalPointer() : slot_() { |
+ internal::ThreadLocalPlatform::AllocateSlot(&slot_); |
+ } |
+ |
+ ~ThreadLocalPointer() { |
+ internal::ThreadLocalPlatform::FreeSlot(slot_); |
+ } |
Type* Get() { |
- return static_cast<Type*>(slot_.Get()); |
+ return static_cast<Type*>( |
+ internal::ThreadLocalPlatform::GetValueFromSlot(slot_)); |
} |
void Set(Type* ptr) { |
- slot_.Set(const_cast<void*>(static_cast<const void*>(ptr))); |
+ internal::ThreadLocalPlatform::SetValueInSlot( |
+ slot_, const_cast<void*>(static_cast<const void*>(ptr))); |
} |
private: |
- ThreadLocalStorage::Slot slot_; |
+ typedef internal::ThreadLocalPlatform::SlotType SlotType; |
+ |
+ SlotType slot_; |
DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); |
}; |
class ThreadLocalBoolean { |
public: |
- ThreadLocalBoolean() = default; |
- ~ThreadLocalBoolean() = default; |
+ ThreadLocalBoolean() {} |
+ ~ThreadLocalBoolean() {} |
bool Get() { |
- return tlp_.Get() != nullptr; |
+ return tlp_.Get() != NULL; |
} |
void Set(bool val) { |
- tlp_.Set(val ? this : nullptr); |
+ tlp_.Set(val ? this : NULL); |
} |
private: |