| // 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_ |