|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // 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. | 
|  | // | 
|  | // 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. | 
|  | // | 
|  | // 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 | 
|  | // 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. | 
|  | // | 
|  | // In Android, the system TLS is limited. | 
|  | // | 
|  | // Example usage: | 
|  | //   // 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); | 
|  | //     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this); | 
|  | //   } | 
|  | // | 
|  | //   MyClass::~MyClass() { | 
|  | //     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL); | 
|  | //     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL); | 
|  | //   } | 
|  | // | 
|  | //   // Return the current MyClass associated with the calling thread, can be | 
|  | //   // NULL if there isn't a MyClass associated. | 
|  | //   MyClass* MyClass::current() { | 
|  | //     return Singleton<ThreadLocalPointer<MyClass> >::get()->Get(); | 
|  | //   } | 
|  |  | 
|  | #ifndef BASE_THREADING_THREAD_LOCAL_H_ | 
|  | #define BASE_THREADING_THREAD_LOCAL_H_ | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/threading/thread_local_storage.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | template <typename Type> | 
|  | class ThreadLocalPointer { | 
|  | public: | 
|  | ThreadLocalPointer() = default; | 
|  | ~ThreadLocalPointer() = default; | 
|  |  | 
|  | Type* Get() { | 
|  | return static_cast<Type*>(slot_.Get()); | 
|  | } | 
|  |  | 
|  | void Set(Type* ptr) { | 
|  | slot_.Set(const_cast<void*>(static_cast<const void*>(ptr))); | 
|  | } | 
|  |  | 
|  | private: | 
|  | ThreadLocalStorage::Slot slot_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); | 
|  | }; | 
|  |  | 
|  | class ThreadLocalBoolean { | 
|  | public: | 
|  | ThreadLocalBoolean() = default; | 
|  | ~ThreadLocalBoolean() = default; | 
|  |  | 
|  | bool Get() { | 
|  | return tlp_.Get() != nullptr; | 
|  | } | 
|  |  | 
|  | void Set(bool val) { | 
|  | tlp_.Set(val ? this : nullptr); | 
|  | } | 
|  |  | 
|  | private: | 
|  | ThreadLocalPointer<void> tlp_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean); | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_THREADING_THREAD_LOCAL_H_ |